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;
    }
    
  • 相关阅读:
    任务调度~Quartz.net实现简单的任务调试
    编译器错误~写JS还是谨慎点好
    编译器错误~不能向ObjectStateManager添加相同的键
    EF架构~将数据库注释添加导入到模型实体类中
    c++ pair类型
    Adobe dreamweaver 5.5安装过程
    c++函数作为参数传递
    c++ vector.clear()
    动态规划之装配线调度问题
    转:VS后缀名详解
  • 原文地址:https://www.cnblogs.com/cjjsb/p/12905839.html
Copyright © 2011-2022 走看看