• CF1261F Xor-Set


    将区间拆分为 ([x2^i,(x+1)2^i)) 的形式,发现两个区间中的数两两异或后形成的仍为一个区间,将 (A,B) 都拆分后区间两两异或会得到 (O(n^2log^2n)) 个区间,取并即为答案,但复杂度无法接受。

    发现对于两个区间 ([x2^i,(x+1)2^i),[y2^j,(y+1)2^j),i>j),其异或后得到的结果仍是高位固定,后 (i) 位任意取,也就是第二个区间中有一段是不用考虑的,这是因为这一段在第一个区间中是任意取的。在线段树上就是只用考虑同一深度的区间,这样得到的区间个数就为 (O(n^2log n)) 了。

    就用线段树来实现即可,(dfs) 的过程中记录当前高位的异或值,当有区间被完全覆盖后就返回。

    #include<bits/stdc++.h>
    #define maxn 100010
    #define maxm 62
    #define p 998244353
    #define inv2 499122177
    #define mid ((l+r)>>1)
    #define mk make_pair
    using namespace std;
    typedef long long ll;
    template<typename T> inline void read(T &x)
    {
    	x=0;char c=getchar();bool flag=false;
    	while(!isdigit(c)){if(c=='-')flag=true;c=getchar();}
    	while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
    	if(flag)x=-x;
    }
    int n;
    vector<pair<int,int> > ve[maxm];
    struct node
    {
    	int root,tot;
    	int ch[maxn][2];
    	bool tag[maxn];
    	void insert(ll L,ll R,ll l,ll r,int &x)
    	{
    		if(!x) x=++tot;
    		if(L<=l&&R>=r)
    		{
    			tag[x]=true;
    			return;
    		}
    		if(L<=mid) insert(L,R,l,mid,ch[x][0]);
    		if(R>mid) insert(L,R,mid+1,r,ch[x][1]);
    	}
    }A,B;
    ll dfs(int d,ll v)
    {
    	for(int i=0;i<ve[d].size();++i)
    	{
    		pair<int,int> t=ve[d][i];
    		if(A.tag[t.first]||B.tag[t.second])
    			return (v+((((ll)1<<d)-1)%p)*inv2%p)%p*(((ll)1<<d)%p)%p;
    	}
    	ll val=0;
    	for(int x=0;x<=1;++x)
    	{
    		ve[d-1].clear();
    		for(int i=0;i<ve[d].size();++i)
    		{
    			pair<int,int> t=ve[d][i];
    			for(int y=0;y<=1;++y)
    				if(A.ch[t.first][y]&&B.ch[t.second][x^y])
    					ve[d-1].push_back(mk(A.ch[t.first][y],B.ch[t.second][x^y]));
    		}
    		if(ve[d-1].size()) val=(val+dfs(d-1,v|((ll)x<<(d-1))))%p;
    	}
    	return val;
    }
    int main()
    {
    	read(n);
    	for(int i=1;i<=n;++i)
    	{
    		ll l,r;
    		read(l),read(r);
    		A.insert(l,r,0,((ll)1<<60)-1,A.root);
    	}
    	read(n);
    	for(int i=1;i<=n;++i)
    	{
    		ll l,r;
    		read(l),read(r);
    		B.insert(l,r,0,((ll)1<<60)-1,B.root);
    	}
    	ve[60].push_back(mk(A.root,B.root)),printf("%lld",dfs(60,0));
    	return 0;
    }
    
  • 相关阅读:
    基金定投是什么?定投的特点?
    Linux环境下MySQL 5.6安装与配置----亲测有效----纯离线安装
    OI生涯回忆录
    NOI2020游记
    Redis操作
    Redis概述
    Memcached
    动态规划——最长回文字符串
    两数之和&无重复字符最长字符串
    黑盒测试常见方法
  • 原文地址:https://www.cnblogs.com/lhm-/p/14461921.html
Copyright © 2020-2023  润新知