时间相对来说还是比较合适的,正好放假就可以打一打啦。
A. New Building for SIS:http://codeforces.com/contest/1020/problem/A
题意概述:有n座楼,每座楼有h层。上一层楼和下一层楼各需要一分钟,在a,b两层之间有跨楼的通道,每次可以走到相邻的楼,时间也是一分钟,给出k组询问,求每组点对之间的最小时间。
打CF学英语。一开始看起来像是最短路,但是画画图就发现并没有那么复杂,首先两栋楼之间的那一段是无论如何都要走的,关键是a,b的限制,其实也很简单,如果楼层高的那个比a低,或者楼层低的那个比b高,就先都走到a层或b层,其他时间直接用大的减去小的就可以。还要注意一点就是如果两个点本来就在同一栋楼上就不用考虑a,b的限制可以直接走。因为这个浪费了两次提交次数...
1 # include <cstdio> 2 # include <iostream> 3 4 using namespace std; 5 6 int n,h,a,b,k; 7 int ta,fa,tb,fb; 8 int ans; 9 10 int main() 11 { 12 scanf("%d%d%d%d%d",&n,&h,&a,&b,&k); 13 if(a>b) swap(a,b); 14 for (int i=1;i<=k;++i) 15 { 16 scanf("%d%d%d%d",&ta,&fa,&tb,&fb); 17 ans=max(ta,tb)-min(ta,tb); 18 if(fa>fb) swap(fa,fb); 19 20 if(ta!=tb) 21 { 22 if(fb<a) ans+=a-fa+a-fb; 23 else if(fa>b) ans+=fa-b+fb-b; 24 else ans+=fb-fa; 25 } 26 else ans+=fb-fa; 27 printf("%d ",ans); 28 } 29 return 0; 30 }
B. Badge:http://codeforces.com/contest/1020/problem/B
题意概述:并不想概述。
数据范围比较小,直接$N^2$模拟。
1 # include <cstdio> 2 # include <iostream> 3 # include <cstring> 4 5 using namespace std; 6 7 int n,x,ans; 8 int p[1005]; 9 bool vis[1005]; 10 11 int main() 12 { 13 scanf("%d",&n); 14 for (int i=1;i<=n;++i) 15 scanf("%d",&p[i]); 16 for (int i=1;i<=n;++i) 17 { 18 memset(vis,0,sizeof(vis)); 19 x=i; 20 while (1) 21 { 22 if(vis[x]) 23 { 24 ans=x; 25 break; 26 } 27 vis[x]=true; 28 x=p[x]; 29 } 30 printf("%d ",ans); 31 } 32 return 0; 33 }
C. Elections:http://codeforces.com/contest/1020/problem/C
题意概述:有n个学生,m个政党,每个学生有支持的政党,但是如果你给他一些钱,他就可以给你想让他投的党投票,现在想付出最少的钱使得1政党有绝对优势(票数严格大于其他党)。$1<=n,m<=3000$
有一种贪心策略是一直收买所需钱最少的学生直到符合条件,但是这样显然是有点问题的,有可能其实只用收买一个收钱多的使得他的政党失败就可以了,但是却收买了许多所需钱虽然少但是无关紧要的人。关键是1号的票数没有确定使得难以贪心,所以考虑枚举最终票数。枚举完票数就开始处理,把每个党超过这个票数且收钱最少的人收买过来,如果这些人都收买完了可是还没有达到预定的票数,就一直收买之前还没有收买过的学生直到人数达标。开long long。
1 # include <cstdio> 2 # include <iostream> 3 # include <cstring> 4 # include <algorithm> 5 6 using namespace std; 7 8 int n,m,ns,cnt[3005],Sum[3005]; 9 struct peo 10 { 11 int p,c,rk; 12 }a[3005]; 13 struct val 14 { 15 int rk,v; 16 }b[3005]; 17 bool vis[3005]; 18 long long min_ans=-1,ans; 19 20 bool cmpa (peo a,peo b) 21 { 22 if(a.p==b.p) return a.c<b.c; 23 return a.p<b.p; 24 } 25 26 bool cmpb (val a,val b) 27 { 28 return a.v<b.v; 29 } 30 31 int main() 32 { 33 scanf("%d%d",&n,&m); 34 for (int i=1;i<=n;++i) 35 { 36 scanf("%d%d",&a[i].p,&a[i].c); 37 a[i].rk=i; 38 b[i].rk=i; 39 b[i].v=a[i].c; 40 } 41 sort(a+1,a+1+n,cmpa); 42 sort(b+1,b+1+n,cmpb); 43 for (int i=1;i<=n;++i) 44 Sum[ a[i].p ]++; 45 for (int s=1;s<=n;++s) 46 { 47 ns=0; 48 ans=0; 49 memset(vis,0,sizeof(vis)); 50 memset(cnt,0,sizeof(cnt)); 51 for (int j=1;j<=n;++j) 52 { 53 if(a[j].p==1) ns++,vis[ a[j].rk ]=true; 54 else 55 { 56 if(Sum[ a[j].p ]-cnt[ a[j].p ]>=s) 57 { 58 vis[ a[j].rk ]=true; 59 cnt[ a[j].p ]++; 60 ans+=a[j].c; 61 ns++; 62 } 63 } 64 } 65 for (int i=1;i<=n;++i) 66 { 67 if(ns>=s) break; 68 if(vis[ b[i].rk ]) continue; 69 ns++; 70 ans+=b[i].v; 71 } 72 if(min_ans==-1) min_ans=ans; 73 min_ans=min(ans,min_ans); 74 } 75 cout<<min_ans; 76 return 0; 77 }
D. The Hat:http://codeforces.com/contest/1020/problem/D
交互题,不会做。
题意概述:n个人排成一个圈。发给每个人一张纸条,问有没有两个正好相对的人拿到了一样的纸条。题意清晰易懂,但是交互部分看不懂,为什么还能返回负数呢...?
E. Sergey's problem:http://codeforces.com/contest/1020/problem/E
题意概述:一个有向无自环图中选出一些点,使得这些点两两间没有连边,且从这些点出发可以用1或2步到达其他所有没被选到的点,有重边。
考试的时候想了好久不会做,赛后看了其他人的代码发现此题做法很奇特,而且至今也没有明白这样做为什么能对。首先贪心的选出一些点使得没选到的点都可以走一步到达,再跑反图贪心地去掉有边相连的点。emmm所以这样怎么就对了呢...虽然找不到反例但是不是很懂,等过几天也许就有详细的题解了吧。
1 # include <cstdio> 2 # include <iostream> 3 # define R register int 4 5 using namespace std; 6 7 const int maxn=1000009; 8 int firs[maxn],x,y,n,m,h,cnt,cs[maxn],re[maxn]; 9 struct edge 10 { 11 int too,nex; 12 }g[maxn]; 13 14 int read() 15 { 16 int x=0; 17 char c=getchar(); 18 while (!isdigit(c)) 19 c=getchar(); 20 while (isdigit(c)) 21 { 22 x=(x<<3)+(x<<1)+(c^48); 23 c=getchar(); 24 } 25 return x; 26 } 27 28 void write (int x) 29 { 30 if(x>=10) write(x/10); 31 putchar(x%10+'0'); 32 } 33 34 void add (int x,int y) 35 { 36 g[++h].too=y; 37 g[h].nex=firs[x]; 38 firs[x]=h; 39 } 40 41 int main() 42 { 43 scanf("%d%d",&n,&m); 44 for (R i=1;i<=m;++i) 45 { 46 x=read(),y=read(); 47 add(x,y); 48 } 49 for (R i=1;i<=n;++i) 50 if(!re[i]) 51 { 52 re[i]=i; 53 for (R j=firs[i];j;j=g[j].nex) 54 if(!re[ g[j].too ]) re[ g[j].too ]=i; 55 cs[i]=true; 56 } 57 for (R i=n;i>=1;--i) 58 if(re[i]==i) 59 if(cs[i]) 60 { 61 for (R j=firs[i];j;j=g[j].nex) 62 cs[ g[j].too ]=false; 63 } 64 for (R i=1;i<=n;++i) 65 if(cs[i]) cnt++; 66 printf("%d ",cnt); 67 for (R i=1;i<=n;++i) 68 if(cs[i]) 69 { 70 write(i); 71 putchar(' '); 72 } 73 return 0; 74 }
---shzr