2019 东北四省赛部分题解 The 13th Chinese Northeast Collegiate Programming Contest
2019-05-27 12:23
387 查看
比赛链接 :https://codeforces.com/gym/102220
J题: 按题意模拟就行
#include<bits/stdc++.h> #define bug1(g) cout<<"test: "<<g<<endl #define bug2(g,i) cout<<"test: "<<g<<" "<<i<<endl #define bug3(g,i,k) cout<<"test: "<<g<<" "<<i<<" "<<k<<endl #define bug4(a,g,i,k) cout<<"test: "<<a<<" "<<g<<" "<<i<<" "<<k<<endl using namespace std; typedef long long ll; ll n; int t; ll a[20]; ll x; int main() { ios::sync_with_stdio(0); cin>>t; while(t--){ cin>>n; cin>>x; ll maxx=x*3; for (int i =2;i<=n;i++) { cin>>a[i]; maxx=max(maxx,a[i]+1); } if(maxx&1) maxx++; cout<<maxx<<endl; } return 0; }
G题: 给N个矩形,每个矩形每次可以上下左右移动一格,问至少几次可以使得有一个方格被所有矩形覆盖
按照出题人的做法
证明在这 https://www.cnblogs.com/xidian-mao/p/7819928.html
代码如下
#include<bits/stdc++.h> #define bug1(g) cout<<"test: "<<g<<endl #define bug2(g,i) cout<<"test: "<<g<<" "<<i<<endl #define bug3(g,i,k) cout<<"test: "<<g<<" "<<i<<" "<<k<<endl #define bug4(a,g,i,k) cout<<"test: "<<a<<" "<<g<<" "<<i<<" "<<k<<endl using namespace std; typedef long long ll; const int maxn=100005; int n; struct node { int xl,xr,yl,yr; }a[maxn]; int x[maxn*2],y[maxn*2]; int cntx,cnty; ll sumx,sumy; int t; int main() { //ios::sync_with_stdio(0); scanf("%d",&t); while(t--){ scanf("%d",&n); cntx=cnty=1; sumx=sumy=0; for(int i =1;i<=n;i++) { scanf("%d %d %d %d",&a[i].xl,&a[i].yl,&a[i].xr,&a[i].yr); sumx+=a[i].xr-a[i].xl; sumy+=a[i].yr-a[i].yl; x[cntx++]=a[i].xl;x[cntx++]=a[i].xr; y[cnty++]=a[i].yl;y[cnty++]=a[i].yr; } sort(x+1,x+cntx); sort(y+1,y+cnty); // bug2(cntx,cnty); --cntx;--cnty; ll xx=x[cntx/2],yy=y[cnty/2]; ll ans=-sumx-sumy; for(int i =1;i<=n;i++) { ans+=abs(a[i].xl-xx)+abs(xx-a[i].xr); ans+=abs(a[i].yl-yy)+abs(yy-a[i].yr); } printf("%lld\n",ans/2); } return 0; }
除了中位数外,我们可以看出这个一维情况下,这个函数是个单峰函数,可以用三分分别求x,y的位置 然后再算总和
#include<bits/stdc++.h> #define bug1(g) cout<<"test: "<<g<<endl #define bug2(g,i) cout<<"test: "<<g<<" "<<i<<endl #define bug3(g,i,k) cout<<"test: "<<g<<" "<<i<<" "<<k<<endl #define bug4(a,g,i,k) cout<<"test: "<<a<<" "<<g<<" "<<i<<" "<<k<<endl using namespace std; typedef long long ll; const int maxn=100005; int n; struct node { int xl,xr,yl,yr; }a[maxn]; int maxx[2],minn[2]; ll sum(int x,int ii) { ll ans=0; if(ii==0) //x for(int i=1;i<=n;i++) { if(a[i].xl<=x&&x<=a[i].xr) continue; else if(x<a[i].xl) ans+=(ll)a[i].xl-x; else ans+=(ll)x-a[i].xr; } else { for(int i=1;i<=n;i++) { if(a[i].yl<=x&&x<=a[i].yr) continue; else if(x<a[i].yl) ans+=(ll)a[i].yl-x; else ans+=(ll)x-a[i].yr; } } return ans; } int sery(int minn,int maxx,int i) { int l =minn,r=maxx; int mid1,mid2; while(r-l>1) { mid1=(l+r)/2; mid2=(mid1+r)/2; ll m1=sum(mid1,i),m2=sum(mid2,i); if(m1<m2) r=mid2; else l=mid1; } return sum(l,i)<sum(r,i)?l:r; } int t; int main() { //ios::sync_with_stdio(0); scanf("%d",&t); while(t--){ scanf("%d",&n); maxx[0]=maxx[1]=-1; minn[0]=minn[1]=1e9+5; for(int i =1;i<=n;i++) { scanf("%d %d %d %d",&a[i].xl,&a[i].yl,&a[i].xr,&a[i].yr); maxx[0]=max(maxx[0],a[i].xr); maxx[1]=max(maxx[1],a[i].yr); minn[0]=min(minn[0],a[i].xl); minn[1]=min(minn[1],a[i].yl); } int xx=sery(minn[0],maxx[0],0),yy=sery(minn[1],maxx[1],1); //bug2(xx,yy); cout<<sum(xx,0)+sum(yy,1)<<endl; } return 0; }
C题: 给N条直线,求有多少对直线有交点(重合也算)
这题卡了精度,用斜率表示一直过不去 ,最后把直线写成AX+BY+C的形式 判断有多少直线重合 有多少重合或平行
假设一共有n条直线 xi条重合 yi条重合或平行
ans=n*(n-1)/2-yi*(yi-1)/2+xi*(xi-1)/2
重合要求A,B,C三个参数都一样,平行或重合只需要A,B一样就行,用map记录一下就ok了
#include<bits/stdc++.h> #define bug1(g) cout<<"test: "<<g<<endl #define bug2(g,i) cout<<"test: "<<g<<" "<<i<<endl #define bug3(g,i,k) cout<<"test: "<<g<<" "<<i<<" "<<k<<endl #define bug4(a,g,i,k) cout<<"test: "<<a<<" "<<g<<" "<<i<<" "<<k<<endl using namespace std; typedef long long ll; const int maxn=100005; struct node { ll a,b,c; friend bool operator <(node a,node b) { if(a.a!=b.a)return a.a<b.a; else if(a.b!=b.b) return a.b<b.b; return a.c<b.c; } }a[maxn],b; map<node,ll>mp1,mp2; ll t,n; int main() { ios::sync_with_stdio(0); cin>>t; while(t--) { ll xa,ya,xb,yb; mp1.clear(); mp2.clear(); cin>>n; for(int i =1;i<=n;i++) { cin>>xa>>ya>>xb>>yb; yb=ya-yb;xb=xa-xb; ll k =__gcd(yb,xb); yb/=k;xb/=k; a[i].a=xb; a[i].b=-yb; a[i].c=yb*xa-xb*ya; if(a[i].a<0) { a[i].a=-a[i].a; a[i].b=-a[i].b; a[i].c=-a[i].c; } b.a=a[i].a,b.b=a[i].b,b.c=0; ++mp1[a[i]];++mp2[b]; } ll ans=n*(n-1)/2; for(auto i =mp1.begin();i!=mp1.end();i++) { ll tmp=i->second; ans+=tmp*(tmp-1)/2; } for(auto i =mp2.begin();i!=mp2.end();i++) { ll tmp=i->second; ans-=tmp*(tmp-1)/2; } cout<<ans<<endl; } return 0; }
H题:
队友写的,我也不会 贴个代码吧
#include <bits/stdc++.h> using namespace std; typedef long long ll; struct Point { ll x, y; bool operator<( Point const& b) const{ return x<b.x||(x==b.x&&y<b.y); } }; struct P { Point a, b; bool operator<( P const& b) const{ return a < b.a ; } }; map<P, int> mp; map<Point, int> mp2; ll gcd(ll a, ll b) { return b == 0 ? a : gcd(b, a%b); } Point solve(Point &a,Point &b) { ll detx = b.x - a.x; ll dety = b.y - a.y; ll gcdd = gcd(detx, dety); // cout << gcdd << endl; detx /= gcdd; dety /= gcdd; if (detx == 0) { a.y = b.y = 0; return Point{-1,-1}; } if (dety == 0) { a.x = b.x = 0; return Point{0,0}; } if (detx < 0) { detx = -detx; dety = -dety; } if (a.x >= 0) { ll tem = a.x / detx; a.x -= detx * tem; a.y -= dety * tem; } else { ll tem = -a.x / detx + 1; a.x += detx * tem; a.y += dety * tem; } if (b.x >= 0) { ll tem = b.x / detx; b.x -= detx * tem; b.y -= dety * tem; } else { ll tem = -b.x / detx + 1; b.x += detx * tem; b.y += dety * tem; } return Point{ detx,dety }; } int main() { int T; scanf("%d", &T); while (T--) { ll ans = 0; mp.clear(); mp2.clear(); int n; scanf("%d", &n); for (int i = 0; i < n; i++) { ll x1, y1, x2, y2; scanf("%lld%lld%lld%lld", &x1, &y1, &x2, &y2); Point a = Point{ x1,y1 }; Point b = Point{ x2,y2 }; Point p=solve(a, b); if (a < b) swap(a, b); P p2 = P{ a,b }; ans += i - mp2+ mp[p2]; mp2[p]++; mp[p2]++; } printf("%I64d\n", ans); } }
B题:有n个糖果m种,每个糖果有两个值ai,bi 代表价值和种类,选择一些糖果,问选择糖果的价值和除以最大的同一种类数的值最大,第i种糖果至少选择l[i]次
[p]枚举分母,选最大的分子就好了,预处理下选择x个糖果的情况下能获得的最大价值和(贪心先选择价值大的)#include<bits/stdc++.h> using namespace std; typedef long long ll; ll n,m; ll t; vector<ll>v[100005]; //每种中的价值有哪些 ll l[100005]; ll s,c; ll ms[100005]; bool cmp(ll a,ll b) { return a>b; } int main() { ios::sync_with_stdio(0); cin>>t; while(t--) { cin>>n>>m; for(int i =1;i<=m;i++) { cin>>l[i]; v[i].clear(); } memset(ms,0,sizeof(ll)*(n+2)); ll x,y; for(int i =1;i<=n;i++) { cin>>x>>y; v[y].push_back(x); } ll maxx=-1; for(int i =1;i<=m;i++) { maxx=max((ll)v[i].size(),maxx); sort(v[i].begin(),v[i].end(),cmp); ll tmp=0; for(int j = 0;j<v[i].size();j++) { tmp+=v[i][j]; if(j+1>=l[i]) //小于l[i]时不算在价值和里 { ms[j+1]+=tmp; tmp=0; } } } ll as=-1,ac=1; for(ll i =1;i<=maxx;i++) //枚举同种最大数量 { ms[i]+=ms[i-1]; if(ms[i]!=0) { s=ms[i];c=i; ll g=__gcd(s,c); s/=g;c/=g; if(as*c<ac*s) { as=s; ac=c; } } } cout<<as<<"/"<<ac<<endl; } }
E题: 给一颗树,问其线图的最小生成树
观察发现,原来的边权相当于线图的点权,线图的边权为两个结点的点权和. 而且对线图来说,他是一些完全图连接的,对完全图求最小生成树只需要将其余点都连向点权最小的点就行
#include<bits/stdc++.h> using namespace std; typedef long long ll; int t; int n; struct node { ll v,w; node(ll a=0,ll b=0) { v=a,w=b; } } ; vector<node>a[100005]; int main() { ios::sync_with_stdio(0); cin>>t; while(t--) { cin>>n; ll x,y,z; for(int i =1;i<=n;i++) a[i].clear(); for(int i =1;i<=n-1;i++) { cin>>x>>y>>z; a[x].push_back(node(y,z)); a[y].push_back(node(x,z)); } ll ans=0; for(int i =1;i<=n;i++) { if(a[i].size()<2) continue; ll minn=0; for(int j =0;j<a[i].size();j++) { if(a[i][j].w<a[i][minn].w) minn=j; } for(int j = 0;j<a[i].size();j++) { if(j!=minn) ans+=a[i][j].w+a[i][minn].w; } } cout<<ans<<endl; } return 0; }
相关文章推荐
- The 13th Zhejiang Provincial Collegiate Programming Contest 部分题解
- The 15th Zhejiang Provincial Collegiate Programming Contest(部分题解)
- The 2018 ACM-ICPC Chinese Collegiate Programming Contest (NingXia) 一些题解
- The 13th Zhejiang Provincial Collegiate Programming Contest - C
- 140 - The 12th Zhejiang Provincial Collegiate Programming Contest(第二部分)
- The 13th Zhejiang Provincial Collegiate Programming Contest - I
- 140 - The 12th Zhejiang Provincial Collegiate Programming Contest(第二部分)
- The 13th Zhejiang Provincial Collegiate Programming Contest - D
- 【ZOJ3941 The 13th Zhejiang Provincial Collegiate Programming ContestF】【贪心 暴力】Kpop Music Party n段part
- The 10th Zhejiang Provincial Collegiate Programming Contest 蒻菜的水题题解。
- 140 - The 12th Zhejiang Provincial Collegiate Programming Contest(2015浙江省赛---第三部分)
- The 13th Zhejiang Provincial Collegiate Programming Contest
- The 13th Zhejiang Provincial Collegiate Programming Contest - I People Counting
- The 10th Zhejiang Provincial Collegiate Programming Contest 蒻菜的水题题解。
- ZOJ 146 - The 13th Zhejiang Provincial Collegiate Programming Contest - C Defuse the Bomb
- The 5th Zhejiang Provincial Collegiate Programming Contest 部分题解
- The 13th Zhejiang Provincial Collegiate Programming Contest - K Highway Project(dij)
- The 13th Zhejiang Provincial Collegiate Programming Contest - K Highway Project
- zoj-5707题 Very Happy Great BG (签到题)The 13th Zhejiang Provincial Collegiate Programming Contest
- The 13th Zhejiang Provincial Collegiate Programming Contest