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 }
“这些年我一直提醒自己一件事情,千万不要自己感动自己。大部分人看似的努力,不过是愚蠢导致的。什么熬夜看书到天亮,连续几天只睡几小时,多久没放假了,如果这些东西也值得夸耀,那么富士康流水线上任何一个人都比你努力多了。人难免天生有自怜的情绪,唯有时刻保持清醒,才能看清真正的价值在哪里。”