CROC-MBTU 2012, Elimination Round (ACM-ICPC)

A....

B...

C.从后向前进行贪心,因为后一半的硬币只能是在取前一半的时候被拿掉,而对于前一半,不能确定到底是由哪种方式拿掉的...

  如果n是偶数,那么拿掉n时,(n/2)*2+1也应该被拿掉,而实际上没有n+1这一堆,所以肯定不行.

C
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #define N 1010
 6 using namespace std;
 7 int s[N];
 8 int main(){
 9     int n;
10     while(cin>>n){
11         for(int i=1;i<=n;i++)cin>>s[i];
12         if(n%2==0||n==1){
13             cout<<-1<<endl;
14             continue;
15         }
16         int ans=0;
17         for(int i=n;i>=2;i-=2){
18             if(s[i]>0||s[i-1]>0){
19                 int maxn=max(s[i],s[i-1]);
20                 s[i]-=maxn;s[i-1]-=maxn;s[i/2]-=maxn;
21                 ans+=maxn;
22             }
23         }
24         if(s[1]>0){
25             ans+=s[1];
26         }
27         cout<<ans<<endl;
28     }
29     return 0;
30 }

D.对于第i列,从上到下进行一次或运算(-1除外)就能得出第i个数的值.

证明如下:考虑(a[i]&a[j])的每一个二进制位,如果从上到下或运算之后,这一位还是1,那么a[i]的这一位一定是1.

  如果运算之后这位是0,有两种可能

      第一种是a[i]这位是1,其他的均是0;

      第二种是a[i]这位是0,其他的随意.

  所以取0的时候不会影响到其他数进行运算,在这里我们就取成0.

按照这样的构造方式,我们可以得到其中一组解,但这不一定是唯一解

D
 1 #include<iostream>
 2 #include<cstring>
 3 #define N 110
 4 using namespace std;
 5 typedef long long ll;
 6 ll s[N][N];
 7 ll ans[N];
 8 int main(){
 9     int n;
10     while(cin>>n){
11         memset(ans,0,sizeof(ans));
12         for(int i=1;i<=n;i++)
13             for(int j=1;j<=n;j++){
14                 cin>>s[i][j];
15                 if(i!=j)ans[j]|=s[i][j];
16             }
17         for(int i=1;i<=n;i++)
18             cout<<ans[i]<<" ";
19         cout<<endl;
20     }
21     return 0;
22 }

E.用两个变量记录一下在里面和在外面的人数即可,最后答案是所有时刻中能看到的最大值

E
 1 #include<iostream>
 2 #include<string>
 3 #include<algorithm>
 4 #include<stack>
 5 using namespace std;
 6 string s;
 7 int main(){
 8     while(cin>>s){
 9         int t1,t2;
10         int ans=0;
11         t1=t2=0;
12         for(int i=0;i<s.size();i++){
13             if(s[i]=='+'){
14                 if(t2>0){
15                     t2--;
16                     t1++;
17                 }
18                 else{
19                     t1++;
20                 }
21             }
22             else if(s[i]=='-'){
23                 if(t1>0){
24                     t1--;
25                     t2++;
26                 }
27                 else t2++;
28             }
29             if(t1>ans||t2>ans)ans=max(t1,t2);
30         }
31         cout<<ans<<endl;
32     }
33     return 0;
34 }

F.模拟.用c++写应该比较恶心...别的语言貌似好写...???.待解决...

G.暴力枚举每两个点,最后统计就好,时间复杂度O(n^2)

G
 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<string>
 5 #include<map>
 6 #define N 10010
 7 using namespace std;
 8 struct Edge{
 9     int u,v,next;
10 }edge[N];
11 int head[N],cnt;
12 string s[N];
13 bool v[N];
14 map<string,int>M;
15 void add(int u,int v){
16     edge[cnt].u=u;edge[cnt].v=v;
17     edge[cnt].next=head[u];
18     head[u]=cnt++;
19 }
20 void init(){
21     cnt=0;
22     memset(head,-1,sizeof(head));
23     M.clear();
24 }
25 int main(){
26     int n;
27     string s1,s2;
28     while(cin>>n){
29         init();
30         int num=0;
31         for(int i=1;i<=n;i++){
32             cin>>s1>>s2;
33             if(!M.count(s1)){
34                 M[s1]=++num;
35                 s[num]=s1;
36             }
37             if(!M.count(s2)){
38                 M[s2]=++num;
39                 s[num]=s2;
40             }
41             add(M[s1],M[s2]);
42             add(M[s2],M[s1]);
43         }
44         cout<<num<<endl;
45         for(int i=1;i<=num;i++){
46             memset(v,0,sizeof(v));
47             v[i]=1;
48             for(int j=head[i];j!=-1;j=edge[j].next)v[edge[j].v]=1;
49             int ans=0,maxn=-1;
50             for(int j=1;j<=num;j++){
51                 if(v[j])continue;
52                 int c=0;
53                 for(int k=head[j];k!=-1;k=edge[k].next)
54                     if(v[edge[k].v])++c;
55                 if(c>maxn){
56                     maxn=c;
57                     ans=1;
58                 }
59                 else if(c==maxn)++ans;
60             }
61             cout<<s[i]<<" "<<ans<<endl;
62         }
63     }
64     return 0;
65 }

H.dp预处理,然后O(1)询问.

 先用O(n^2)的时间判断s[i....j]是不是回文字串,然后再进行dp

  dp[i][j]=dp[i][j-1]+dp[i+1][j]-dp[i+1][j-1]...

H
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<iostream>
 5 #define N 5010
 6 using namespace std;
 7 char s[N];
 8 bool flag[N][N];
 9 int dp[N][N];
10 
11 void init(){
12     memset(flag,0,sizeof(flag));
13     memset(dp,0,sizeof(dp));
14     s[0]='#';
15     int n=strlen(s);
16     for(int i=1;i<=n;i++)flag[i][i]=1;
17     for(int len=2;len<=n;len++){
18         for(int i=1;i+len-1<=n;i++){
19             int j=i+len-1;
20             if(s[i]!=s[j])continue;
21             if(len==2||flag[i+1][j-1])
22                 flag[i][j]=1;
23         }
24     }
25     for(int len=1;len<=n;len++)
26         for(int i=1;i+len-1<=n;i++)
27             dp[i][i+len-1]=dp[i+1][i+len-1]+dp[i][i+len-2]-dp[i+1][i+len-2]+flag[i][i+len-1];
28 }
29 
30 int main(){
31     int n;
32     while(~scanf("%s%d",s+1,&n)){
33         init();
34         int x,y;
35         while(n--){
36             scanf("%d%d",&x,&y);
37             printf("%d\n",dp[x][y]);
38         }
39     }
40     return 0;
41 }

 

 

posted @ 2012-11-21 21:41  silver__bullet  阅读(102)  评论(0编辑  收藏  举报