2015 ACM/ICPC Asia Regional Changchun Online
1001 Alisha’s Party
比赛的时候学长stl吃T。手写堆过。
赛后我贴了那两份代码都过。相差.2s。
于是用stl写水果。
1 # include <iostream> 2 # include <cstdio> 3 # include <algorithm> 4 # include <queue> 5 using namespace std; 6 # define maxk 151000 7 int ans[maxk]; 8 9 struct node 10 { 11 char name[300]; 12 int id,val; 13 friend bool operator < (node x,node y) 14 { 15 if(x.val!=y.val) return x.val<y.val; 16 return x.id>y.id; 17 } 18 } p[maxk]; 19 priority_queue<node> pq; 20 21 struct open 22 { 23 int t,p; 24 } T[maxk]; 25 26 bool cmp(open x,open y) 27 { 28 return x.t<y.t; 29 } 30 31 int main(void) 32 { 33 int kase; cin>>kase; 34 while(kase--) 35 { 36 int k,m,q,pos=1,cnt=0,Q; 37 scanf("%d%d%d",&k,&m,&q); 38 for(int i=1;i<=k;i++) 39 { 40 scanf("%s%d",p[i].name,&p[i].val); 41 p[i].id=i; 42 } 43 for(int i=0;i<m;i++) scanf("%d%d",&T[i].t,&T[i].p); 44 sort(T,T+m,cmp); 45 while(!pq.empty()) pq.pop(); 46 for(int i=0;i<m;i++) 47 { 48 while(pos<=k&&pos<=T[i].t) pq.push(p[pos++]); 49 while(!pq.empty()&&T[i].p--) 50 { 51 ans[++cnt]=pq.top().id; 52 pq.pop(); 53 } 54 } 55 while(pos<=k) pq.push(p[pos++]); 56 while(!pq.empty()) 57 { 58 ans[++cnt]=pq.top().id; 59 pq.pop(); 60 } 61 for(int i=1;i<q;i++) 62 { 63 scanf("%d",&Q); 64 printf("%s ",p[ans[Q]].name); 65 } 66 scanf("%d",&Q); 67 printf("%s\n",p[ans[Q]].name); 68 } 69 return 0; 70 }
1002 Ponds
赛时题意错理解成对所有奇数联通子集权值求和……
先dfs或kahn删点。
再遍历一遍所有奇数联通即可。
1 # include <iostream> 2 # include <cstdio> 3 # include <cstring> 4 using namespace std; 5 typedef long long LL; 6 const int maxp=10010,maxm=100010; 7 int cnt,headlist[maxp],v[maxp],deg[maxp]; 8 bool vis[maxp]; 9 LL tmp; 10 11 struct node 12 { 13 int to,pre; 14 } edge[2*maxm]; 15 16 void add(int from,int to) 17 { 18 cnt++; 19 edge[cnt].pre=headlist[from]; 20 edge[cnt].to=to; 21 headlist[from]=cnt; 22 return; 23 } 24 25 void dfs1(int pos) 26 { 27 deg[pos]=0; vis[pos]=1; 28 for(int i=headlist[pos];i;i=edge[i].pre) 29 { 30 int to=edge[i].to; 31 if(deg[to]) deg[to]--; 32 if(deg[to]==1) dfs1(to); 33 } 34 return; 35 } 36 37 int dfs2(int pos) 38 { 39 int ret=1; 40 vis[pos]=1; 41 tmp+=v[pos]; 42 for(int i=headlist[pos];i;i=edge[i].pre) 43 { 44 int to=edge[i].to; 45 if(vis[to]) continue; 46 ret+=dfs2(to); 47 } 48 return ret; 49 } 50 51 int main(void) 52 { 53 int T; cin>>T; 54 while(T--) 55 { 56 cnt=0; 57 memset(headlist,0,sizeof(headlist)); 58 memset(deg,0,sizeof(deg)); 59 memset(vis,0,sizeof(vis)); 60 int p,m; scanf("%d%d",&p,&m); 61 for(int i=1;i<=p;i++) scanf("%d",v+i); 62 for(int i=0;i<m;i++) 63 { 64 int a,b; scanf("%d%d",&a,&b); 65 add(a,b); add(b,a); 66 deg[a]++; deg[b]++; 67 } 68 for(int i=1;i<=p;i++) if(deg[i]==1) dfs1(i); 69 LL ans=0; 70 for(int i=1;i<=p;i++) if(!vis[i]&°[i]) 71 { 72 tmp=0; 73 if(dfs2(i)%2) ans+=tmp; 74 } 75 printf("%I64d\n",ans); 76 } 77 return 0; 78 }
1003 Aggregated Counting
1004 Clock Adjusting
1005 Travel
赛场题意理解错。哭。
询问排序。并查集按秩合并。对答案的贡献是2*r[u]*r[v]。
1 # include <iostream> 2 # include <cstdio> 3 # include <algorithm> 4 using namespace std; 5 int Ans[5010],pa[21000],r[21000]; 6 7 int Find(int x) 8 { 9 return pa[x]==x?x:pa[x]=Find(pa[x]); 10 } 11 12 void Union(int x,int y) 13 { 14 x=Find(x),y=Find(y); 15 if(y<x) swap(x,y); 16 pa[y]=x; r[x]+=r[y]; 17 return; 18 } 19 20 struct node 21 { 22 int from,to,val; 23 friend bool operator < (node x,node y) 24 { 25 return x.val<y.val; 26 } 27 } edge[100100]; 28 29 struct Query 30 { 31 int no,x; 32 friend bool operator < (Query a,Query b) 33 { 34 return a.x<b.x; 35 } 36 }query[5010]; 37 38 int main(void) 39 { 40 int T; cin>>T; 41 while(T--) 42 { 43 int n,m,q; scanf("%d%d%d",&n,&m,&q); 44 for(int i=1;i<=n;i++){pa[i]=i;r[i]=1;} 45 for(int i=0;i<m;i++) 46 scanf("%d%d%d",&edge[i].from,&edge[i].to,&edge[i].val); 47 sort(edge,edge+m); 48 for(int i=0;i<q;i++) 49 { 50 query[i].no=i; 51 scanf("%d",&query[i].x); 52 } 53 sort(query,query+q); 54 int pos=0,ans=0; 55 for(int i=0;i<q;i++) 56 { 57 while(pos<m&&edge[pos].val<=query[i].x) 58 { 59 int u=Find(edge[pos].from),v=Find(edge[pos].to); 60 pos++; 61 if(u==v) continue; 62 ans+=2*r[v]*r[u]; 63 Union(u,v); 64 } 65 Ans[query[i].no]=ans; 66 } 67 for(int i=0;i<q;i++) printf("%d\n",Ans[i]); 68 } 69 return 0; 70 }
1006 Favorite Donut
讨论这个题目经历了几个阶段。
比赛时只知道用最大表示法。
然而由于最大表示法在有多解时返回index最小的。逆时针的处理方法没想好。场上T了。
赛后想到逆时针多解时必成循环。可以用KMP求循环节。两者都是O(n)。
后来经过学长提醒。最大表示法如果处理循环串是k增到m后跳出。
于是可以直接在最大表示法里处理掉循环节。时间上常数优化(并无)。
1 # include <iostream> 2 # include <cstdio> 3 # include <cstring> 4 # include <algorithm> 5 # include <cmath> 6 using namespace std; 7 char s[20005]; 8 int m; 9 10 int getMax(int p) 11 { 12 int i=0,j=1,k=0; 13 while(i<m&&j<m&&k<m) 14 { 15 int t=s[(i+k)%m]-s[(j+k)%m]; 16 if(!t) k++; 17 else 18 { 19 if(t<0) i=max(i+k+1,j+1); 20 else j=max(j+k+1,i+1); 21 k=0; 22 } 23 } 24 if(p&&k==m) return m-1-(m-1-min(i,j))%abs(i-j); 25 return min(i,j); 26 } 27 28 int main(void) 29 { 30 int T; cin>>T; 31 while(T--) 32 { 33 scanf("%d%s",&m,s); 34 int op=0,a=getMax(0),b; 35 reverse(s,s+m); 36 b=getMax(1); 37 for(int i=0;i<m;i++) 38 { 39 if(s[(2*m-1-a-i)%m]>s[(b+i)%m]) {op=1; break;} 40 if(s[(2*m-1-a-i)%m]<s[(b+i)%m]) {op=2; break;} 41 } 42 if(op==1) printf("%d 0\n",a+1); 43 else if(op==2) printf("%d 1\n",m-b); 44 else if(a+1<=m-b) printf("%d 0\n",a+1); 45 else printf("%d 1\n",m-b); 46 } 47 return 0; 48 }
1007 The Water Problem
水题。ST/线段树/暴力。
1 # include <iostream> 2 # include <cstdio> 3 # include <cmath> 4 # include <algorithm> 5 using namespace std; 6 # define maxn 1000+5 7 int num[maxn],MAX[maxn][20]; 8 9 int main(void) 10 { 11 int T; cin>>T; 12 while(T--) 13 { 14 int N,Q; scanf("%d",&N); 15 for(int i=1;i<=N;i++) 16 { 17 scanf("%d",num+i); 18 MAX[i][0]=num[i]; 19 } 20 for(int j=1;j<12;j++) 21 for(int i=1;i<=N;i++) 22 if(i+(1<<j)-1<=N) 23 MAX[i][j]=max(MAX[i][j-1],MAX[i+(1<<j-1)][j-1]); 24 scanf("%d",&Q); 25 for(int i=0;i<Q;i++) 26 { 27 int m,n; scanf("%d%d",&m,&n); 28 int k=(log(double(n-m+1))/log(2)); 29 int ans=max(MAX[m][k],MAX[n-(1<<k)+1][k]); 30 printf("%d\n",ans); 31 } 32 } 33 return 0; 34 }
1008 Elven Postman
1009 Food Problem
1010 Unknown Treasure
1011 Good Numbers
1012 Marisa’s Cake
1013 Robot Dog