2015 Multi-University Training Contest 7

1001 Game On the Tree

1002 Tree Maker

1003 Hotaru's problem

Manacher处理好p数组。

暴力举一下公共串即可。

 1 # include <iostream>
 2 # include <cstdio>
 3 # include <algorithm>
 4 using namespace std;
 5 const int maxn=100100;
 6 int s[maxn*2],p[maxn*2];
 7 
 8 int main(void)
 9 {
10     int T; cin>>T;
11     for(int kase=1;kase<=T;kase++)
12     {
13         int N; scanf("%d",&N);
14         int len=2*N+1;
15         s[0]=-1; s[len+1]=-2;
16         s[len]=0;
17         for(int i=2;i<=2*N+1;i+=2)
18         {
19             s[i-1]=0;
20             scanf("%d",s+i);
21         }
22         int mx=0,id;
23         for(int i=1;i<=len;i++)
24         {
25             if(mx>i) p[i]=min(p[2*id-i],mx-i);
26             else p[i]=1;
27             while(s[i+p[i]]==s[i-p[i]]) p[i]++;
28             if(p[i]+i>mx) { mx=p[i]+i; id=i; }
29         }
30         int m=0;
31         for(int i=1;i<=len;i+=2)
32             for(int j=p[i];j>m&&j>2;j-=2)
33                 if(p[i+j-1]>=j) m=max(m,j);
34         int ans=m/2*3;
35         printf("Case #%d: %d
",kase,ans);
36     }
37     return 0;
38 }
Aguin

1004 Segment Game

因为区间长度是递增的。

所以新的线段不可能被已有的线段所覆盖。

所以算比新线段右端点小的右端点数减去比新线段左端点小的左端点数就是答案。

范围是1e9。先离散化。

 1 # include <iostream>
 2 # include <cstdio>
 3 # include <cstring>
 4 # include <algorithm>
 5 using namespace std;
 6 # define maxn 200100
 7 int n,a[maxn],b[maxn],l[maxn],r[maxn];
 8 int c1[2*maxn],c2[2*maxn],tem[2*maxn];
 9 
10 int lowbit(int s)
11 {
12     return s&(-s);
13 }
14 
15 void update(int i,int x,int op)
16 {
17     int *c;
18     if(op==1) c=c1;
19     else if (op==2) c=c2;
20     while(i<=2*maxn){c[i]+=x;i+=lowbit(i);}
21     return;
22 }
23 
24 int query(int i,int op)
25 {
26     int *c;
27     if(op==1) c=c1;
28     else if (op==2) c=c2;
29     int ret=0;
30     while(i>0){ret+=c[i];i-=lowbit(i);}
31     return ret;
32 }
33 
34 int main(void)
35 {
36     int kase=0;
37     while(~scanf("%d",&n))
38     {
39         memset(c1,0,sizeof(c1));
40         memset(c2,0,sizeof(c2));
41         int cnt=0,num=0;
42         for(int i=1;i<=n;i++)
43         {
44             scanf("%d%d",a+i,b+i);
45             if(a[i]==0)
46             {
47                 num++;
48                 tem[++cnt]=b[i];
49                 tem[++cnt]=b[i]+num;
50             }
51         }
52         sort(tem+1,tem+cnt+1);
53         int tot=unique(tem+1,tem+cnt+1)-tem-1;
54         num=0;
55         printf("Case #%d:
",++kase);
56         for(int i=1;i<=n;i++)
57         {
58             if(a[i]==0)
59             {
60                 num++;
61                 l[num]=lower_bound(tem+1,tem+tot,b[i])-tem;
62                 r[num]=lower_bound(tem+1,tem+tot,b[i]+num)-tem;
63                 printf("%d
",query(r[num],2)-query(l[num]-1,1));
64                 update(l[num],1,1);
65                 update(r[num],1,2);
66             }
67             else if(a[i]==1)
68             {
69                 update(l[b[i]],-1,1);
70                 update(r[b[i]],-1,2);    
71             }
72         }
73     }
74     return 0;
75 }
Aguin

1005 The shortest problem

发现现在自己也会找签到题了- -。

敲到一半的时候发现有两个队A了。果然是最水的题。

不过调了一会QAQ。 

 1 # include <iostream>
 2 # include <cstdio>
 3 # include <algorithm>
 4 using namespace std;
 5 typedef long long LL;
 6 
 7 int main(void)
 8 {
 9     for(int kase=1;;kase++)
10     {
11         int n,t; scanf("%d%d",&n,&t);
12         if(n==-1) break;
13         bool is_odd;
14         LL odd=0,even=0,sum=n;
15         for(int i=0;i<=t;i++)
16         {
17             LL tem=sum,todd=0,teven=0;
18             is_odd=1;
19             while(sum)
20             {
21                 LL mod=sum%(LL)10;
22                 if(is_odd) todd+=mod;
23                 else teven+=mod;
24                 sum/=(LL)10;
25                 is_odd=!is_odd;
26             }
27             if(!is_odd) swap(odd,even);
28             odd+=todd; even+=teven;
29             sum=even+odd;
30         }
31         printf("Case #%d: ",kase);
32         if((max(odd,even)-min(odd,even))%(LL)11) puts("No");
33         else puts("Yes");
34     }
35     return 0;
36 }
Aguin

1006 Tetris

纯模拟。本来看别人写了三四五六百行都不敢写了。

后来下了标程看了下只有100+。于是按着题解思路自己写了。

还得先回Clarification把题意读懂再写- -。

 1 # include <iostream>
 2 # include <cstdio>
 3 # include <cstring>
 4 using namespace std;
 5 int cnt,x,y,squ,dir;
 6 int square[3][4][4][4],map[10][13],type[1000],rot[]={1,2,4};
 7 char s[1100];
 8 
 9 bool in(int xx,int yy){return xx>0&&xx<10&&yy>0;}
10 bool check(int s,int d,int xx,int yy)
11 {
12     for(int i=0;i<4;i++)
13         for(int j=0;j<4;j++)
14             if(square[s][d][i][j])
15                 if(!in(xx+i,yy+j)||map[xx+i][yy+j])
16                     return false;
17     return true;
18 }
19 
20 bool dec(void)
21 {
22     if(!check(squ,dir,x,y-1)) return false;
23     y--; return true;
24 }
25 
26 void mov(void)
27 {
28     cnt++;
29     if(s[cnt]=='w'&&check(squ,(dir+1)%rot[squ],x,y)) dir=(dir+1)%rot[squ];
30     else if(s[cnt]=='a'&&check(squ,dir,x-1,y)) x--;
31     else if(s[cnt]=='d'&&check(squ,dir,x+1,y)) x++;
32     else if(s[cnt]=='s') dec();
33     return;
34 }
35 
36 int eli(void)
37 {
38     for(int i=0;i<4;i++)
39         for(int j=0;j<4;j++)
40             if(square[squ][dir][i][j])
41                 map[x+i][y+j]=1;
42     int ret=0,mark[4]={0};
43     for(int j=0;j<4;j++)
44     {
45         int yes=1;
46         for(int i=1;i<=9;i++)
47             if(!map[i][y+j]){yes=0;break;}
48         if(yes)
49         {
50             for(int i=1;i<=9;i++) map[i][y+j]=0;
51             ret++; mark[j]=1;
52         }
53     }
54     for(int j=0;j<4;j++)
55     {
56         while(mark[j])
57         {
58             for(int i=y+j;i<12;i++)
59                 for(int k=1;k<=9;k++)
60                     map[k][i]=map[k][i+1];
61             for(int i=j;i<3;i++)
62                 mark[i]=mark[i+1];
63             mark[3]=0;
64         }
65     }
66     return ret;
67 }
68 
69 int main(void)
70 {
71     square[0][0][0][0]=square[0][0][0][1]=square[0][0][1][0]=square[0][0][1][1]=1;
72     square[1][0][0][0]=square[1][0][0][1]=square[1][0][0][2]=square[1][0][0][3]=1;
73     square[1][1][0][0]=square[1][1][1][0]=square[1][1][2][0]=square[1][1][3][0]=1;
74     square[2][0][0][0]=square[2][0][0][1]=square[2][0][1][0]=square[2][0][2][0]=1;
75     square[2][1][0][0]=square[2][1][0][1]=square[2][1][0][2]=square[2][1][1][2]=1;
76     square[2][2][0][1]=square[2][2][1][1]=square[2][2][2][1]=square[2][2][2][0]=1;
77     square[2][3][0][0]=square[2][3][1][0]=square[2][3][1][1]=square[2][3][1][2]=1;
78     int T; cin>>T;
79     for(int kase=1;kase<=T;kase++)
80     {
81         int n; scanf("%d",&n);
82         scanf("%s",s+1);
83         for(int i=1;i<=n;i++) scanf("%d",type+i);
84         memset(map,0,sizeof(map));
85         int ans=0; cnt=0;
86         for(int i=1;i<=n;i++)
87         {
88             x=4,y=9,squ=type[i],dir=0;
89             while(1)
90             {
91                 mov();
92                 if(!dec()) break;
93             }
94             ans+=eli();
95         }
96         printf("Case %d: %d
",kase,ans);
97     }
98     return 0;
99 }
Aguin

1007 Gray code

第一位没处理好。调了蛮久。

按照百度百科里说的。把第零位当成0就好。

我是找连续的?串。如果个数为奇且?串两端的相同或者个数为偶两端不同。

就必然可以调整问号使得格雷码全为1。(怎么取不重要。全加上就是。)

如果不是上面两种情况。那么必然可以调整成一个0。其余全是1。

那么找到问号串对应的a[n]中最小的剔除。其余全部加上即可。

 1 # include <iostream>
 2 # include <cstdio>
 3 # include <cstring>
 4 # include <algorithm>
 5 using namespace std;
 6 # define maxn 200100
 7 int a[maxn];
 8 char s[maxn];
 9 
10 int main(void)
11 {
12     int T; cin>>T;
13     for(int kase=1;kase<=T;kase++)
14     {
15         scanf("%s",s+1);
16         int len=strlen(s+1);
17         for(int i=1;i<=len;i++) scanf("%d",a+i);
18         int ans=0; s[0]='0';
19         for(int i=1;i<=len;i++)
20         {
21             if(s[i]=='?')
22             {
23                 int j,tem=0,Min=10000;
24                 for(j=i;j<=len&&s[j]=='?';j++)
25                 {
26                     tem+=a[j];
27                     Min=min(Min,a[j]);
28                 }
29                 if(j>len) {ans+=tem; break;}
30                 else if(((j-i)%2==1&&s[i-1]==s[j])||((j-i)%2==0&&s[i-1]!=s[j])) ans+=tem+a[j];
31                 else
32                 {
33                     Min=min(Min,a[j]);
34                     ans+=tem+a[j]-Min;        
35                 }
36                 i=j;
37             }
38             else if(s[i]!=s[i-1]) ans+=a[i];
39         }
40         printf("Case #%d: %d
",kase,ans);
41     }
42     return 0;
43 }
Aguin

1008 Convex Polygon

1009 Root

1010 Leader in Tree Land

1011 Mahjong tree

因为前面正好做过点树dp。所以看到这个觉得四点前能过。

结果五点都没过。一直越界。后来出门坐三轮车上才想起来全局变量起重名了。邻表没初始化。

(最后知道真相的我眼泪掉下来。

说下写法。

因为怕写错。写了两个dfs。

先dp一下每个子树节点。如果有一个根有超过两个不是叶子的子节点。就是不合法的。

在合法的情况下再dp答案。

每个节点的答案就是子节点答案乘积再乘上叶子节点数的阶乘。

另外若这个节点有非叶子的子树。答案乘2。

相当于一个的时候可以把它放在左边或者右边。两个的时候可以互换。

最后1这个根节点。可以选1或者n两个。所以最后答案再乘2。

然后回家改完还是wa。发现一个坑点。 

n为1的时候最后答案不用乘2。QAQ。

 1 # pragma comment(linker, "/STACK:102400000,102400000")
 2 # include <iostream>
 3 # include <cstdio>
 4 # include <cstring>
 5 using namespace std;
 6 typedef long long LL;
 7 const LL mod=1e9+7;
 8 # define maxn 100100
 9 int cnt,headlist[maxn],node[maxn],ok;
10 LL fac[maxn],ans[maxn];
11 
12 struct node
13 {
14     int to,pre;
15 } edge[2*maxn];
16 
17 void add(int from,int to)
18 {
19     cnt++;
20     edge[cnt].pre=headlist[from];
21     edge[cnt].to=to;
22     headlist[from]=cnt;
23 }
24 
25 void dfs1(int pos,int fa)
26 {
27     node[pos]=1;
28     int num=0;
29     for(int i=headlist[pos];i;i=edge[i].pre)
30     {
31         int to=edge[i].to;
32         if(to==fa) continue;
33         dfs1(to,pos);
34         if(node[to]>1) num++;
35         if(num>2) ok=0;
36         node[pos]+=node[to];
37     }
38     return;
39 }
40 
41 void dfs2(int pos,int fa)
42 {
43     int num=0,tot=0;
44     ans[pos]=1;
45     for(int i=headlist[pos];i;i=edge[i].pre)
46     {
47         int to=edge[i].to;
48         if(to==fa) continue;
49         dfs2(to,pos);
50         tot++;
51         if(node[to]==1) num++;
52         ans[pos]=(ans[pos]*ans[to])%mod;
53     }
54     if(tot-num) ans[pos]=(ans[pos]*(LL)2)%mod;
55     ans[pos]=(ans[pos]*fac[num])%mod;
56     return;
57 }
58 
59 int main(void)
60 {
61     fac[0]=(LL)1;
62     for(int i=1;i<maxn;i++) fac[i]=(fac[i-1]*(LL)i)%mod;
63     int T; cin>>T;
64     for(int kase=1;kase<=T;kase++)
65     {
66         cnt=0;
67         memset(headlist,0,sizeof(headlist));
68         int n; scanf("%d",&n);
69         for(int i=1;i<n;i++)
70         {
71             int u,v;
72             scanf("%d%d",&u,&v);
73             add(u,v);
74             add(v,u);
75         }
76         ok=1; dfs1(1,0);
77         if(!ok) {printf("Case #%d: 0
",kase); continue;}
78         dfs2(1,0);
79         if(n>1) ans[1]=(ans[1]*(LL)2)%mod;
80         printf("Case #%d: %I64d
",kase,ans[1]);
81     }
82     return 0;
83 }
Aguin
原文地址:https://www.cnblogs.com/Aguin/p/4722455.html