B题:Crazy Binary String
这个B题最长01子序列这个就很明显了
我们取0,1中最少的那个数的2倍,这样的话,显然是最优的 这个还是很好做的
但是我们对这个01均衡的串的话我们该怎么操作呢?
一个很naive的想法是这个串有什么性质呢: 0 1 的数量相同 ,那么 0 1就可以相互抵消 ,只要两个对于对应的奇数位和两个对应的偶数位中间的01能互相消掉的话
那么我们可以就可以算贡献,这个的话就随便搞搞就ok了
还有一钟想法是二分长度,然后check,这个是有问题的 比如说 11000011 这个的话8是可以,4是不行的
关于这个杨例怎么造呢,我也不知道啊????????????????????????????????
这个也没啥办法,只能靠自己领会了
下面是代码:
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <iostream> 5 #include <cmath> 6 #include <bitset> 7 typedef long long ll; 8 using namespace std; 9 const int maxn=(int)(1e5+2000); 10 int n; 11 char s[maxn]; 12 int qilen[maxn*2],oulen[maxn*2]; 13 int main(){ 14 scanf("%d",&n); 15 scanf("%s",s+1); 16 memset(qilen,-1,sizeof(qilen)); 17 memset(oulen,-1,sizeof(oulen)); 18 int cnt0=0,cnt1=0; 19 int ans=0; 20 oulen[maxn]=0; 21 int q=maxn; 22 //cout<<q<<endl; 23 for(int i=1;i<=n;i++){ 24 if(s[i]=='0') cnt0++; 25 else cnt1++; 26 if(s[i]=='0') q--; 27 else q++; 28 // cout<<q<<endl; 29 if(i%2==1){ 30 if(qilen[q]==-1) qilen[q]=i; 31 else{ 32 ans=max(ans,(i-qilen[q])); 33 } 34 }else{ 35 if(oulen[q]==-1) oulen[q]=i; 36 else ans=max(ans,i-oulen[q]); 37 } 38 } 39 printf("%d %d\n",ans,2*min(cnt0,cnt1)); 40 return 0; 41 }
H题:Magic Line
这个题的话我们首先想一下怎么分成两半,一个最简单的想法是排序,排完序之后
因为是偶数个吗,中点自然就出现了
然后在中间的点把他们分开,具体用一个两个1e9,-1e9的点来分开就ok,这样还是挺好操作的。大概一下子就能搞掉
下面是代码:
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <iostream> 5 #include <cmath> 6 #include <bitset> 7 typedef long long ll; 8 using namespace std; 9 const int maxn=1100; 10 const ll Max=(ll)(1e9); 11 int t,n; 12 struct point{ 13 ll xi,yi; 14 }; 15 point sum[maxn]; 16 17 bool cmp(point p1,point p2){ 18 if(p1.xi==p2.xi) return p1.yi<p2.yi; 19 else return p1.xi<p2.xi; 20 } 21 22 int main(){ 23 scanf("%d",&t); 24 while(t--){ 25 scanf("%d",&n); 26 for(int i=1;i<=n;i++) scanf("%lld%lld",&sum[i].xi,&sum[i].yi); 27 sort(sum+1,sum+n+1,cmp); 28 int m=n/2; 29 if(sum[m].xi==sum[m+1].xi){ 30 if((sum[m+1].yi-sum[m].yi)%2==1){ 31 printf("%lld %lld %lld %lld\n",sum[m].xi-1,(ll)(3e8)+sum[m+1].yi,sum[m].xi+1,sum[m].yi-(ll)(3e8)); 32 }else{ 33 ll y=(sum[m+1].yi+sum[m].yi)/2; 34 printf("%lld %lld %lld %lld\n",sum[m].xi-1,(ll)(3e8)+y,sum[m].xi+1,y-(ll)(3e8)); 35 } 36 }else{ 37 ll y=(sum[m].yi+sum[m+1].yi)/2; 38 printf("%lld %lld %lld %lld\n",sum[m].xi,y+(ll)(3e8),sum[m+1].xi,y-(ll)(3e8)); 39 } 40 } 41 return 0; 42 }
F题:Planting Trees
这个的话我们怎么搞呢?????
首先我们知道如果我们要得到最大的区间,在根据他给的数据,知道这个东西某种情况下是需要穷举的,这个的话是要靠我们来努力发现的。
我觉得每道acm题目都是一道道模拟题, 他会给你一个条件,然后我们根据这些条件,应用上来,用这些应用上来的东西发现一个一个的性质,最后
根据性质我们得出这个题目的做法,这个是一般的Acm题的做法