zoukankan      html  css  js  c++  java
  • luoguP3292 [SCOI2016]幸运数字(点分治做法)

    题意

    考虑点分治,每次处理过重心的询问(即两点在重心的不同子树中)。

    求出每个点到重心的线性基,之后对过重心的询问合并两点线性基求解。

    code:

    #include<bits/stdc++.h>
    using namespace std;
    #define pii pair<int,int>
    #define mkp make_pair
    #define fir first
    #define sec second
    typedef long long ll;
    const int maxn=20010;
    const int maxm=200010;
    const int inf=1e9;
    int n,m,cnt,root,maxsize=inf,trsize;
    int head[maxn],size[maxn],check[maxn];
    ll a[maxn],ans[maxm];
    bool vis[maxn];
    vector<pii>ve[maxn];
    struct edge{int to,nxt;}e[maxn<<1];
    struct Xord
    {
    	ll d[65];
    	Xord(){memset(d,0,sizeof(d));}
    	inline void clear(){memset(d,0,sizeof(d));}
    	inline void insert(ll x)
    	{
    		for(int i=61;~i;i--)
    		{
    			if(!(x&(1ll<<i)))continue;
    			if(!d[i]){d[i]=x;return;}
    			else x^=d[i];
    		}
    	}
    	inline ll query()
    	{
    		ll res=0;
    		for(int i=61;~i;i--)res=max(res,res^d[i]);
    		return res;
    	}
    }xord[maxn];
    inline void add(int u,int v)
    {
    	e[++cnt].nxt=head[u];
    	head[u]=cnt;
    	e[cnt].to=v;
    }
    void getroot(int x,int fa)
    {
    	size[x]=1;
    	int maxx=0;
    	for(int i=head[x];i;i=e[i].nxt)
    	{
    		int y=e[i].to;
    		if(y==fa||vis[y])continue;
    		getroot(y,x);size[x]+=size[y];
    		maxx=max(maxx,size[y]);
    	}
    	maxx=max(maxx,trsize-size[x]);
    	if(maxx<maxsize)maxsize=maxx,root=x;
    }
    void getxor(int x,int fa)
    {
    	xord[x]=xord[fa];xord[x].insert(a[x]);
    	for(unsigned int i=0;i<ve[x].size();i++)
    	{
    		int y=ve[x][i].fir;
    		if(check[y]!=root)continue;
    		Xord tmp=xord[x];
    		for(int j=0;j<=60;j++)if(xord[y].d[j])tmp.insert(xord[y].d[j]);
    		ans[ve[x][i].sec]=max(ans[ve[x][i].sec],tmp.query());
    	}
    	for(int i=head[x];i;i=e[i].nxt)
    	{
    		int y=e[i].to;
    		if(y==fa||vis[y])continue;
    		getxor(y,x);
    	}
    }
    void mark(int x,int fa,int k)
    {
    	check[x]=k;
    	for(int i=head[x];i;i=e[i].nxt)
    	{
    		int y=e[i].to;
    		if(y==fa||vis[y])continue;
    		mark(y,x,k);
    	}
    }
    void solve(int x)
    {
    	//cerr<<x<<endl;
    	vis[x]=1;check[x]=x;
    	xord[x].clear();xord[x].insert(a[x]);
    	for(int i=head[x];i;i=e[i].nxt)
    	{
    		int y=e[i].to;
    		if(vis[y])continue;
    		getxor(y,x);mark(y,x,x);
    	}
    	for(int i=head[x];i;i=e[i].nxt)
    	{
    		int y=e[i].to;
    		if(vis[y])continue;
    		maxsize=inf;trsize=size[y];getroot(y,0);
    		solve(root);
    	}
    }
    int main()
    {
    	//freopen("test.in","r",stdin);
    	//freopen("test.out","w",stdout);
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
    	for(int i=1;i<n;i++)
    	{
    		int u,v;scanf("%d%d",&u,&v);
    		add(u,v),add(v,u);
    	}	
    	for(int i=1;i<=m;i++)
    	{
    		int x,y;scanf("%d%d",&x,&y);
    		if(x==y)ans[i]=a[x];
    		else ve[x].push_back(mkp(y,i)),ve[y].push_back(mkp(x,i));
    	}
    	trsize=n;maxsize=inf;getroot(1,0);
    	solve(root);
    	for(int i=1;i<=m;i++)printf("%lld
    ",ans[i]);
    	return 0;
    }
    
  • 相关阅读:
    Week7 作业 A
    Mouth 1 模拟题 CSP201512-3 画图
    C++出现:error: passing 'const Employee' as 'this' argument of 'int Employee::getSalary()' discards qualifiers [-fpermissive]
    C++出现error: no match for call to '(MyCompare) (const key_type&, const Person&)'
    CentOS 7出现ifconfig:command not found
    有效清理C盘内存
    重装系统之后出现https:/ / logincdn.msauth.net/shared/1.0/content/js/ConvergedLogin_PCore_xxvbETmiVPe1AsI9xwHp3A2.js
    C++/QT运行时出现void value not ignored as it ought to be
    运行QT项目文件夹下的exe文件提示找不到“各种dll”
    Ubuntu16.04配置OpenCV3.2.0
  • 原文地址:https://www.cnblogs.com/nofind/p/12031688.html
Copyright © 2011-2022 走看看