zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    Eclipse 代码提示功能设置。
    eclipse android 查看源文件 出错的解决办法
    Android 中自定义控件和属性(attr.xml,declarestyleable,TypedArray)的方法和使用
    android屏幕尺寸 sp,px,dp,density,in介绍
    用C#实现的条形码和二维码编码解码器 之转载
    在Eclipse下如何导入jar安装包
    C# 获取往控件中拖进的文件或文件夹的信息(转)
    c#中Dictionary、ArrayList、Hashtable和数组的区别是什么?[转]
    C#中的枚举
    C#结构体特性
  • 原文地址:https://www.cnblogs.com/lhm-/p/14461921.html
Copyright © 2011-2022 走看看