zoukankan      html  css  js  c++  java
  • BZOJ2217:Lollipop

    题意

    给定一个由1和2组成的序列,多次询问是否存在一个区间满足区间和=x

    分析

    结论:假如存在一个子串和为x,那么一定存在一个前缀,和为x或x+1
    证明:可以认为原串是由和为x的串在开头和结尾添加若干数得到,再后边添加数不会对产生和为x或x+1的前缀产生影响,所以只考虑在前边添加数,认为后边多余的数可以删掉
    若原来是一个和为x或x+1的串,那么如果在前边添加的数和最后一个数相等,去掉最后一个数之后依然是一个和为x或x+1的串
    考虑新添加的数和最后的数不同的情况
    若原来和为x,在前边添加1,那么这就变成了和为x+1的串;再前边添加2,把结尾的1去掉,则变成了和为x+1的串
    若原来和为x+1,在前边添加1,把后边的2删掉,就变成了和为x的串;在前边添加2,把结尾的1去掉之后,若新的结尾是1,把1去掉之后变成和为x+1的串,若新的结尾是2,把2去掉之后变为和为x的串。一定存在新的结尾,即原来串的长度不可能为1,因为串的和为x+1而最后一个数是1,并且x>0

    找到和为x直接输出,找到x+1时如何找到x?
    我们将1-i这一段向右移,如果找到a[l]=1||a[r]=1那么就能找到x,那么我们设置nxt[i]表示从i出发的连续2序列的长度,有以下两种情况

    (1.nxt[1]<nxt[i],l=nxt[1]+1+1,r=i+nxt[i])
    这时候能够保证a[r]为2,而l为什么加2,因为加1的话就等于x+1,所以要再右移一位减去1,这里请思考一下
    (2.nxt[1]>=nxt[i],l=nxt[i]+1,r=nxt[i]+i,这里要保证r<=n)
    这时候a[l]为2,a[r]为1

    trick

    代码

    #include <cstdio>
    const int maxn = 1001000;
    int n,m,q;
    char s[maxn];
    int mp[maxn<<1],l,r,nxt[maxn];
    
    int main()
    {
    	scanf("%d %d",&n,&m);
    	scanf("%s",s);
    	int ret=0;
    	for(int i=0;i<n;++i)
    	{
    		ret+=(s[i]=='W')?1:2;
    		mp[ret]=i+1;
    	}
    	for(int i=n-1;i>=0;--i) nxt[i+1]=(s[i]=='W')?0:nxt[i+2]+1;
    	while(m--)
    	{
    		scanf("%d",&q);
    		if(mp[q]) puts("TAK");
    		else if(mp[q+1])
    		{
    			int i=mp[q+1];
    			if(nxt[1]<nxt[i]) puts("TAK");
    			else if(nxt[1]>=nxt[i]&&i+nxt[i]<=n) puts("TAK");
    			else puts("NIE");
    		}
    		else puts("NIE");
    	} 
    	return 0;
    }
    
  • 相关阅读:
    ChemDraw绘制DNA结构的技巧
    几何画板中该如何插入公式
    MathType可以编辑带圈乘号吗
    几何画板是这样构造扇形内部的
    Chem 3D软件可以改变背景吗
    移动端上下滑动事件之--坑爹的touch.js
    在HTML5中如何提高网站前端性能
    git入门
    php 路由实现
    vb 定时执行php程序
  • 原文地址:https://www.cnblogs.com/chendl111/p/7074854.html
Copyright © 2011-2022 走看看