• bzoj 4811 由乃的OJ


    bzoj 4811 由乃的OJ

    • 考虑树链剖分.
    • 树剖后用一颗线段树维护一段连续区间,类似于一个函数,各位上进入 (0/1) ,输出的数字分别是什么.注意到最多只有 (64) 位,可以用一个 (unsigned long long) 的大数状压表示,合并两段区间时推导一下可以做到 (O(1)) .
    • 注意 (3 种)位运算混在一起,满足交换律,却不满足结合律,所以从区间左/右侧进入同一个数,最后得到的数不同.需要维护两个方向的函数.
    • 修改时在线段树上单点修改就好,查询用树剖的基本操作,先找出 (x o y) 这一段的函数,再贪心构造解.
    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define mp make_pair
    #define pii pair<int,int>
    typedef unsigned long long ull;
    ull read(){
        ull nm=0,fh=1;char cw=getchar();
        for(;!isdigit(cw);cw=getchar()) ;
        for(;isdigit(cw);cw=getchar()) nm=nm*10+(cw-'0');
        return nm*fh;
    }
    const int MAXN=2e5+10;
    ull cnt=0,head[MAXN],to[MAXN<<1],nx[MAXN<<1];
    inline void addedge(ull u,ull v)
    {
    	++cnt;
    	to[cnt]=v;
    	nx[cnt]=head[u];
    	head[u]=cnt;
    }
    inline void ins(ull u,ull v)
    {
    	addedge(u,v);
    	addedge(v,u);
    }
    const unsigned long long U1=1;
    ull fa[MAXN],siz[MAXN],mxson[MAXN],top[MAXN],dfn[MAXN],rnk[MAXN],dep[MAXN],idx=0;
    void dfs1(ull u)
    {
    	siz[u]=U1;
    	dep[u]=dep[fa[u]]+U1;
    	for(ull i=head[u];i>0;i=nx[i])
    		{
    			ull v=to[i];
    			if(v==fa[u])
    				continue;
    			fa[v]=u;
    			dfs1(v);
    			siz[u]+=siz[v];
    			if(siz[v]>siz[mxson[u]])
    				mxson[u]=v;
    		}
    }
    void dfs2(ull u,ull Tp)
    {
    	dfn[u]=++idx;
    	rnk[idx]=u;
    	top[u]=Tp;
    	if(mxson[u]>0)
    		dfs2(mxson[u],Tp);
    	for(ull i=head[u];i>0;i=nx[i])
    		{
    			ull v=to[i];
    			if(v==fa[u] || v==mxson[u])
    				continue;
    			dfs2(v,v);
    		}
    }
    inline ull calc(ull x,ull bas,ull op)
    {
    	if(op==1)
    		return x&bas;
    	if(op==2)
    		return x|bas;
    	return x^bas;
    }
    ull val[MAXN],opt[MAXN];
    unsigned long long maxv=0;
    struct node{
    	ull l,r;
    	ull d[2][2];//d[左入/右入][全0/全1] 
    	void init(ull v,ull op)
    		{
    			d[0][0]=d[1][0]=calc(0,v,op);
    			d[0][1]=d[1][1]=calc(maxv,v,op);
    		}
    	void merge(node L,node R)
    		{		
    			d[0][0]=(L.d[0][0]&R.d[0][1])|((~L.d[0][0])&R.d[0][0]);
    	        d[1][0]=(R.d[1][0]&L.d[1][1])|((~R.d[1][0])&L.d[1][0]);
    	        d[0][1]=(L.d[0][1]&R.d[0][1])|((~L.d[0][1])&R.d[0][0]);
    	        d[1][1]=(R.d[1][1]&L.d[1][1])|((~R.d[1][1])&L.d[1][0]);
    		}
    	void inverse()
    		{
    			swap(d[0][0],d[1][0]);
    			swap(d[0][1],d[1][1]);
    		}
    };
    struct SegmentTree{
    	#define root Tree[o]
    	#define lson Tree[o<<1]
    	#define rson Tree[o<<1|1]
    	node Tree[MAXN<<2];
    	void BuildTree(ull o,ull l,ull r)
    		{
    			root.l=l,root.r=r;
    			if(l==r)
    				{
    					root.init(val[rnk[l]],opt[rnk[l]]);
    					return;
    				}
    			ull mid=(l+r)>>1;
    			BuildTree(o<<1,l,mid);
    			BuildTree(o<<1|1,mid+1,r);
    			root.merge(lson,rson);
    		}
    	void update(ull o,ull pos,ull newv,ull newopt)
    		{
    			ull l=root.l,r=root.r;
    			if(l==r)
    				{
    					root.init(newv,newopt);
    					return;
    				}
    			ull mid=(l+r)>>1;
    			if(pos<=mid)
    				update(o<<1,pos,newv,newopt);
    			else
    				update(o<<1|1,pos,newv,newopt);
    			root.merge(lson,rson);
    		}
    	node query(ull o,ull L,ull R)
    		{
    			ull l=root.l,r=root.r;
    			if(L<=l && r<=R)
    				return root;
    			node res;
    			res.init(0,3);
    			if(l>R || r<L)
    				return res;
    			res.merge(query(o<<1,L,R),query(o<<1|1,L,R));
    			return res;
    		}
    }T;
    ull n,m,k;
    void init()
    {
    	ull rt=(n+1)>>1;
    	fa[rt]=0;
    	for(ull i=0;i<k;i++) 
    		maxv+=(U1<<i);
    	dfs1(rt);
    	dfs2(rt,rt);
    	T.BuildTree(1,1,n);
    }
    ull solve(ull x,ull y,ull lim)
    {
    	ull tot=0;
    	node res1,res2,cur;
    	res1.init(0,3);
    	res2.init(0,3);
    	while(top[x]!=top[y])
    		{
    			if(dep[top[x]]>dep[top[y]])
    				{
    					res1.merge(T.query(1,dfn[top[x]],dfn[x]),res1);
    					x=fa[top[x]];
    				}
    			else
    				{
    					res2.merge(T.query(1,dfn[top[y]],dfn[y]),res2);
    					y=fa[top[y]];
    				}
    		}
    	if(dep[x]>dep[y])
    		{
    			node c=T.query(1,dfn[y],dfn[x]);
    			res1.merge(c,res1);
    		}		
    	else
    		{
    			node c=T.query(1,dfn[x],dfn[y]);
    			res2.merge(c,res2);
    		}
    	res1.inverse();
    	cur.merge(res1,res2);
    	for(ull i=k;i-->0;)
    		{
    			if(cur.d[0][0] & (U1<<i))
    				tot+=(U1<<i);
    			else if( ( (cur.d[0][1]) & (U1<<i) ) >0 && lim>=(U1<<i) )
    				lim-=(U1<<i),tot+=(U1<<i);
    		}
    	return tot;
    }
    int main()
    {
    	n=read(),m=read(),k=read();
    	for(ull i=1;i<=n;++i)
    		opt[i]=read(),val[i]=read();
    	for(ull i=1;i<n;++i)
    		{
    			ull u=read(),v=read();
    			ins(u,v);
    		}
    	init();
    	while(m--)
    		{
    			ull op=read();
    			ull x=read(),y=read(),z=read();
    			if(op==1)
    				cout<<solve(x,y,z)<<endl;
    			else
    				T.update(1,dfn[x],z,y);
    		}
    	return 0;
    }
    
  • 相关阅读:
    Github进不去解决方法
    微信小程序中使用iconfont的方法
    curl实现SFTP上传下载文件
    curl实现SFTP上传下载文件
    curl不支持sftp的解决方法
    sscanf遇到回车换行认为字符串结束,怎样让它忽略这些回车换行继续搜索整个字符串?
    史上最全阿里 Java 面试题总结及答案
    VS Code的Error: Running the contributed command: ‘_workbench.downloadResource‘ failed解决
    云锵投资 2021 年 07 月简报
    看完段永平的100条思考,我终于悟出他为何这么牛…(转载)
  • 原文地址:https://www.cnblogs.com/jklover/p/10410285.html
Copyright © 2020-2023  润新知