qduoj 79 翻转游戏 经典牛翻地问题 思维

来源:互联网 发布:播放ppt需要网络吗 编辑:程序博客网 时间:2024/06/07 01:19

题目链接

思路:

           这道题是从poj上的改编而来,但做法完全一样。

   首先明确的就是交换区间的翻转顺序无影响,一个区间翻转两次以上是多余的。我们首先看最左端的棋子,包含这个棋子的区间只有一个,如果这个棋子是黑色的,那么这个区间一定需要翻转,翻转完了这个,在往右寻找棋子为黑色的棋子去翻转(翻转它所在的整个区间),复杂度为n方(如果真的去实现翻转的话).肯定TLE。

   我们可以这样优化,f[i]表示i到i+k-1 是否就行翻转,翻转为1否则为0.这个对于当前的棋子i,其前面区间的翻转次数就可以确定了为s= f[i-k+1]....f[i-1],这时候就可以判断当前棋子的颜色,以及是否需要翻转了.另外对于第i+1个棋子来说,它前面所包含它的区间的翻转次数为 ss=s+f[i+1]-f[i-k+1].这样每一次的的翻转次数就可以O(1)的求出来了.

#include<bits/stdc++.h>#define Ri(a) scanf("%d", &a)#define Rl(a) scanf("%lld", &a)#define Rf(a) scanf("%lf", &a)#define Rs(a) scanf("%s", a)#define Pi(a) printf("%d\n", (a))#define Pf(a) printf("%lf\n", (a))#define Pl(a) printf("%lld\n", (a))#define Ps(a) printf("%s\n", (a))#define W(a) while(a--)#define CLR(a, b) memset(a, (b), sizeof(a))#define MOD 1000000007#define inf 0x3f3f3f3f#define exp 0.00000001#define  pii  pair<int, int>#define  mp   make_pair#define  pb   push_backusing namespace std;typedef long long ll;const int maxn=1e5+10;char s[maxn];int k,m;int f[maxn],dir[maxn];ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}int solve(){int res=0;int sum=0;int len=strlen(s);for(int i=0;i+k<=len;i++){int a=s[i]-'0';if((a+sum)%2!=0){res++;f[i]=1;}sum+=f[i];if(i-k+1>=0)sum-=f[i-k+1];}for(int i=len-k+1;i<len;i++){int a=s[i]-'0';if((a+sum)%2!=0)return -1;sum-=f[i-k+1];// }if(res>m)return -1;return 1;}int main(){int t;Ri(t);W(t){CLR(f,0);Ri(k),Ri(m);Rs(s);int flag=solve();if(flag==-1)Ps("NO");elsePs("YES");}return 0;}