• P5522 [yLOI2019] 棠梨煎雪(线段树、状压)


    首先看到题目要求实现区间询问和单点修改,又发现题目有一条特殊性质——(nleq30)。由此可以想到对 (m) 建一棵线段树,每个节点维护字符串压缩后的信息。

    接下来思考如何状压这个字符串。字符串中有三种字符 0,1,?。可以将 0 状压为 ((10)_2)1 状压为 ((01)_2)? 状压为 ((11)_2)。每次问一个区间内字符串的方案数就相当于将所有点进行 & 运算,这样可以保证 ? 在碰到 01 的时候可以直接变成对应数字,而当一个 01& 运算的时候对应值会变为 0 ,在查询的时候方便特判无解的情况。

    以上操作对修改同理。


    一些小细节:线段树走到空区间的时候传一个 unsigned long long 型的二进制位均为 1 的整数即可。

    #include<bits/stdc++.h>
    
    using namespace std;
    
    #define int long long
    #define Int unsigned long long
    
    template<typename _T>
    inline void read(_T &x)
    {
    	x=0;char s=getchar();int f=1;
    	while(s<'0'||s>'9') {f=1;if(s=='-')f=-1;s=getchar();}
    	while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+s-'0';s=getchar();}
    	x*=f;
    }
    
    #define lowbit(x) (x&(-x))
    #define gb(x) ((x-1)/T + 1)
    #define gl(x) ((x-1)*T + 1)
    #define pb push_back
    #define fi first
    #define sd second
    #define Re register
    #define MOD(x) (x = (x + mod)%mod)
    #define pii pair<int,int>
    
    const int np = 1e5 + 15;
    
    char c[np][40];
    unsigned int INF;
    int a[np];
    char s[np];
    
    struct node{
    	int l,r;
    	int state;
    	node *ls,*rs;
    	
    	inline bool inrange(int L,int R){return L <= l && r <= R;}
    	inline bool outofrange(int L,int R){return r<L||R<l;} 
    
    	inline void pushup()
    	{
    		state = ls->state & rs->state ; 
    	}
    	
    	inline void upd(int L,int R,int vl)
    	{
    		if(inrange(L,R))
    		{
    			state = vl;
    			return;
    		}
    		else
    		{
    			if(!outofrange(L,R))
    			{
    				ls->upd(L,R,vl);
    				rs->upd(L,R,vl);
    				pushup();
    			}
    			else return;
    		}
    	}
    	
    	inline int query(int L,int R)
    	{
    		if(inrange(L,R))
    		{
    			return state;
    		}
    		else
    		{
    			if(!outofrange(L,R))
    			{
    				return ls->query(L,R) & rs->query(L,R);
    			}
    			else return INF;
    		}
    	}
    }mem[np * 2],*pool = mem,*rot;
    inline node *New(){return ++pool;}
    inline node *build(int L,int R)
    {
    	node *u = New();
    	u->l = L, u->r = R;
    	if(L == R)
    	{
    		u->ls = u->rs = NULL;
    		u->state = a[L];
    	}
    	else
    	{
    		int mid = L + R >> 1;
    		u->ls = build(L,mid);
    		u->rs = build(mid + 1,R);
    		u->pushup();
    	}
    	return u;
    }
    
    inline int solve(char *g,int len)
    {
    	int state = 0;
    	for(int i=1;i<=len;i++)
    	{
    		if(g[i] == '1')
    		{
    			state += 1ll<<(2*(i-1));
    		}
    		if(g[i] == '0')
    		{
    			state += 2ll<<(2*(i-1));
    		}
    		if(g[i] == '?')
    		{
    			state += 3ll<<(2*(i-1));
    		}
    	}
    	return state;	
    }
    
    signed main()
    {
    	INF = 0;
    	INF--;
    	int n,m,q;
    	read(n);
    	read(m);
    	read(q);
    	for(int i=1;i<=m;i++)
    	{
    		scanf("%s",c[i] + 1);
    		int op = strlen(c[i] + 1);
    		a[i] = solve(c[i],op);
    	}
    	
    	rot = build(1,m);
    	
    	int Ans = 0;
    	for(int i=1,opt,l,r,pos;i<=q;i++)
    	{
    		read(opt);
    		switch(opt)
    		{
    			case 0:{
    				read(l);
    				read(r);
    				int k = rot->query(l,r);
    				int g = 3,ans = 0;
    				for(int i=0;i<2 * n;i+=2)
    				{
    					if((g<<i&k) == g<<i) ans++;
    					if(!((k>>i)&3))
    					{
    						ans = -1;
    						break;
    					}
    				 } 
    				if(ans == -1) Ans ^= 0;
    				else Ans ^= (1ll<<ans);
    
    				break;
    			}
    			case 1:{
    				read(pos);
    				scanf("%s",s+1);
    				int p_ = solve(s,strlen(s + 1));
    				rot->upd(pos,pos,p_);
    				break;
    			}
    		}
    	}
    	printf("%lld
    ",Ans);
     }
    

    End

    2020 年暑假 @一扶苏一 给我们讲了线段树,这种指针形式实现的线段树就是当年的成果。这道题就是当时的作业题,当时机房里只有 cyc 做了出来。当时扶苏和 cyc 一块给我们讲了很久,但是仍旧不明白如何实现。当一年之后,我已经熟练掌握了状压和线段树,再看到这个题,心里只想着一句话「这题似乎不是特别难」,即使这样,这题在我心里也有着不同于其它题目的分量。

    感谢扶苏学长。撒花~

  • 相关阅读:
    linux(cat,more,less,head)——对文件显示进行查看操作
    linux(ln)
    Linux(touch)
    Linux(cp)
    Linux(rmdir,rm,mv)
    Linux(mkdir)
    一个对象是否能够引用该类其他实例的私有成员?
    圆角图标
    android.content.ReceiverCallNotAllowedException问题解决
    list view item高度设置
  • 原文地址:https://www.cnblogs.com/-Iris-/p/15350239.html
Copyright © 2020-2023  润新知