zoukankan      html  css  js  c++  java
  • Luogu P5607 [Ynoi2013]无力回天NOI2017

    白给的一眼题。话说ynoi的题目名竟然与ACG无关了爷青结

    题目的操作显然是让你用线性基维护,众所周知线性基是可以合并的,复杂度是(O(log^2 a_i))

    所以容易想出用线段树来维护线性基,复杂度(O(nlog nlog^2 a_i))和符合复杂度的样子

    但是这里是区间修改啊,总不能一次重构一堆线性基吧

    考虑利用异或的性质,我们小小地差分一下,令(b_i=a_{i-1}operatorname{xor} a_i),那么区间修改的时候只需要修改(b_l,b_{r+1})

    那么问题来了,询问的时候我的线性基里就不是我想要的({a_l,a_{l+1},cdots,a_r}),那怎么搞?

    考虑我们搞出({a_l,b_{l+1},b_{l+2},cdots,b_r})({a_l,a_loperatorname{xor} a_{l+1},a_{l+1}operatorname{xor} a_{l+2}cdots,a_{r-1}operatorname{xor} a_r})

    由于线性运算和线性基的定义我们发现在这个集合中随便异或来异或去和原来的({a_l,a_{l+1},cdots,a_r})等效

    然后就做完了,(a_i=operatorname{Xor}_{j=1}^i b_j),线段树上顺带维护下即可,总体复杂度(O(nlog nlog^2 a_i))

    精准地写完一发入魂

    #include<cstdio>
    #include<cstring>
    #define RI register int
    #define CI const int&
    using namespace std;
    const int N=50005,P=30;
    int n,m,a[N],b[N],opt,x,y,z;
    struct LB
    {
    	int v[P];
    	inline LB() { memset(v,0,sizeof(v)); }
    	inline void clear(void) { memset(v,0,sizeof(v)); }
    	inline void insert(int x)
    	{
    		for (RI i=P-1;~i;--i) if ((x>>i)&1)
    		{
    			if (!v[i]) return (void)(v[i]=x); x^=v[i];
    		}
    	}
    	inline int query(int x)
    	{
    		for (RI i=P-1;~i;--i) if ((x^v[i])>x) x^=v[i]; return x;
    	}
    	friend inline LB operator + (const LB& A,const LB& B)
    	{
    		LB C; RI i; for (i=0;i<P;++i) C.v[i]=A.v[i];
    		for (i=0;i<P;++i) if (B.v[i]) C.insert(B.v[i]); return C;
    	}
    }t;
    class Segment_Tree
    {
    	private:
    		struct segment
    		{
    			int xsum; LB l;
    		}node[N<<2];
    		#define S(x) node[x].xsum
    		#define L(x) node[x].l
    		#define TN CI now=1,CI l=1,CI r=n
    		#define LS now<<1,l,mid
    		#define RS now<<1|1,mid+1,r
    		inline void pushup(CI now)
    		{
    			S(now)=S(now<<1)^S(now<<1|1); L(now)=L(now<<1)+L(now<<1|1);
    		}
    	public:
    		inline void build(TN)
    		{
    			if (l==r) return S(now)=b[l],L(now).insert(b[l]);
    			int mid=l+r>>1; build(LS); build(RS); pushup(now);
    		}
    		inline void updata(CI pos,CI val,TN)
    		{
    			if (pos>n) return; if (l==r) return S(now)=val,L(now).clear(),L(now).insert(val);
    			int mid=l+r>>1; if (pos<=mid) updata(pos,val,LS); else updata(pos,val,RS); pushup(now);
    		}
    		inline LB query(CI beg,CI end,TN)
    		{
    			if (beg>end) return LB(); if (beg<=l&&r<=end) return L(now); LB ret; int mid=l+r>>1;
    			if (beg<=mid) ret=ret+query(beg,end,LS); if (end>mid) ret=ret+query(beg,end,RS); return ret;
    		}
    		inline int presum(CI beg,CI end,TN)
    		{
    			if (beg<=l&&r<=end) return S(now); int mid=l+r>>1,ret=presum(beg,end,LS);
    			if (end>mid) ret^=presum(beg,end,RS); return ret;
    		}
    		#undef S
    		#undef L
    		#undef TN
    		#undef LS
    		#undef RS
    }SEG;
    int main()
    {
    	RI i; for (scanf("%d%d",&n,&m),i=1;i<=n;++i) 
    	scanf("%d",&a[i]),b[i]=a[i-1]^a[i]; for (SEG.build(),i=1;i<=m;++i)
    	{
    		scanf("%d%d%d%d",&opt,&x,&y,&z);
    		if (opt==1) SEG.updata(x,b[x]^=z),SEG.updata(y+1,b[y+1]^=z);
    		else t=SEG.query(x+1,y),t.insert(SEG.presum(1,x)),printf("%d
    ",t.query(z));
    	}
    	return 0;
    }
    
  • 相关阅读:
    LoadRunne遇到的一些问题FAQ(持续更新...)
    LoadRunner11下载、安装与破解
    LoadRunner之录制你的第一个脚本
    appium+Linux环境安装配置
    appium-FAQ(持续更新...)
    appium启动运行log分析
    利用Unity3D与Oculus实现机器情绪安抚师的一种方案
    利用Unity3D实现多平台增强现实网络游戏的一种方案
    Ubuntu16.04安装NVIDIA驱动时的一些坑与解决方案
    你的计算机也可以看懂世界——十分钟跑起卷积神经网络(Windows+CPU)
  • 原文地址:https://www.cnblogs.com/cjjsb/p/12905839.html
Copyright © 2011-2022 走看看