HDU5583 Kingdom of Black and White

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5583

知识点:void)

题目大意:

  现有一个 01 串,定义一个量 strength 为串中所有连续的 0 子串或者 1 子串的长度的平方的总和。现改变串中的一个元素(0改为1,1改为0,也可选择不修改),使得该串的 strength 最大,求该最大值。

  暴力解决。

  把串根据 0 和 1 分成多个块:111000110111 --> 111 000 11 0 111

  枚举改变各块的首字母再往前一位的字母和末字母再往后一位的字母所能得到的最大的 strength 即可,需要注意的一点是:长度只有 1 的块一改变就会跟前后的块连成一块。

AC代码:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 
 5 using namespace std;
 6 typedef long long ll;
 7 const int maxn=1e5+5;
 8 char inp[maxn];
 9 int s[maxn],e[maxn];    //s[i]:第i块的头坐标;e[i]:第i块的尾坐标。
10 int main()
11 {
12     int T;
13     scanf("%d",&T);
14     for(int t=1;t<=T;t++){
15         scanf("%s",inp);
16         printf("Case #%d: ",t);
17         int len=strlen(inp);
18         
19         int cnt=0,now=inp[0]-'0';   //cnt:块数
20         s[0]=0;
21         for(int i=1;i<len;i++){
22             if(inp[i]-'0'!=now){
23                 e[cnt]=i-1;
24                 cnt++;
25                 s[cnt]=i;
26                 now=inp[i]-'0';
27             }
28         }
29         e[cnt++]=len-1;
30         
31         if(cnt==1){
32             printf("%lld\n",(ll)len*len);
33             continue;
34         }
35         
36         ll ending=0,head=0;     //head:i-2 之前的 strength值;ending:i+2 之后的 strength值
37         for(int i=cnt-1;i>1;i--)
38             ending+=(e[i]-s[i]+1)*(e[i]-s[i]+1);
39             
40         ll ans=0,n1,n2;
41         for(int i=0;i<cnt;i++){
42             if(i+2<cnt) ending-=(e[i+2]-s[i+2]+1)*(e[i+2]-s[i+2]+1);    //更新ending
43         
44             n1=n2=0;
45             if(i<cnt-1){//改变块后一位的元素,n1记录答案
46                 if(i<cnt-2&&e[i+1]-s[i+1]==0)//第 i+1 块只有一个元素的情况,把第 i,i+1,i+2 块连成一块
47                     n1=ending+head+(e[i+2]-s[i]+1)*(e[i+2]-s[i]+1);
48                 else{   //正常的更新,第 i 块加 1,第 i+1 块减 1
49                     n1=ending+head+(e[i+1]-s[i+1])*(e[i+1]-s[i+1])+(e[i]-s[i]+2)*(e[i]-s[i]+2);
50                     if(i<cnt-2) n1+=(e[i+2]-s[i+2]+1)*(e[i+2]-s[i+2]+1);
51                 }
52                 
53                 if(i>0) n1+=(e[i-1]-s[i-1]+1)*(e[i-1]-s[i-1]+1);    //将第 i-1 
54                 if(i-1>0)   n1+=(e[i-2]-s[i-2]+1)*(e[i-2]-s[i-2]+1);//和 i-2 块加上去
55                 
56                 ans=max(ans,n1);
57             }
58             
59             if(i>0){//改变块前一位的元素,n2记录答案,与上类似
60                 if(i>1&&e[i-1]-s[i-1]==0)
61                     n2=ending+head+(e[i]-s[i-2]+1)*(e[i]-s[i-2]+1);
62                 else{
63                     n2=ending+head+(e[i-1]-s[i-1])*(e[i-1]-s[i-1])+(e[i]-s[i]+2)*(e[i]-s[i]+2);
64                     if(i>1) n2+=(e[i-2]-s[i-2]+1)*(e[i-2]-s[i-2]+1);
65                 }
66                 if(i+1<cnt)   n2+=(e[i+1]-s[i+1]+1)*(e[i+1]-s[i+1]+1);
67                 if(i+2<cnt) n2+=(e[i+2]-s[i+2]+1)*(e[i+2]-s[i+2]+1);
68                 ans=max(ans,n2);
69             }
70             if(i-2>=0)  head+=(e[i-2]-s[i-2]+1)*(e[i-2]-s[i-2]+1);
71         }
72         printf("%lld\n",ans);
73     }
74     return 0;
75 }

 

posted @ 2017-11-17 03:12  Blogggggg  阅读(183)  评论(0编辑  收藏  举报