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 }
Aguin

 

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]&&deg[i])
71         {
72             tmp=0;
73             if(dfs2(i)%2) ans+=tmp;
74         }
75         printf("%I64d\n",ans);
76     }
77     return 0;
78 }
Aguin

 

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 }
Aguin

 

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 }
Aguin

 

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 }
Aguin

 

1008 Elven Postman

 

1009 Food Problem

 

1010 Unknown Treasure

 

1011 Good Numbers

 

1012 Marisa’s Cake

 

1013 Robot Dog

 

posted @ 2015-09-13 20:55  Aguin  阅读(262)  评论(0编辑  收藏  举报