zoukankan      html  css  js  c++  java
  • [CTSC2008]网络管理

    [CTSC2008]网络管理

    这个题看到维护链上路径,看起来很像是树剖,但是用线段树+树链剖分显然还要二分答案,这就三个log了,于是考虑复杂度更加优秀的做法.
    线段树套树状数组(带修改主席树),主席树有道经典的板子题.Dynamic Rankings
    那个是区间,这个是树上路径,其实大同小异.根据树的dfn序列,建线段树.
    你做修改的时候,相当于把dfn序列中([dfn[x],dfn[x]+sz[x]-1])之间的点修改了嘛.
    想象一下一排一模一样整齐的二叉树,优美地排列在你面前,这个时候一下把这些线段树们都压在一坨,每个二叉树的节点都开一个树状数组来维护前缀和.,然后你在这颗棵压扁的线段树上,没走到一个节点,就把这个节点的那个树状数组拿出来,查询或者修改你要的信息.
    这样空间复杂度看起来是(n^2)的,所以显然要动态开点,树状数组也要动态开点.
    注意树上单点修改是区间修改,所以树状数组是差分了的,单点查询相当于前缀和查询.
    还有就是一定要离散化你的权值.

    又臭又长的代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define maxn 80005
    #define mid ((l+r)>>1)
    using namespace std;
    int n,m,tim,p,tot,Q,cnt1,cnt0,sz;
    int seq[maxn],b[maxn<<1],s[maxn*400],lc[maxn*400],rc[maxn*400];
    int tmp[2][maxn],dep[maxn],dfn[maxn],fa[maxn][20],size[maxn],rt[maxn];
    struct node{int k,a,b;}q[maxn];
    int head[maxn],nxt[maxn<<1],to[maxn<<1],cnt;
    void add(int u,int v){nxt[++cnt]=head[u];head[u]=cnt;to[cnt]=v;}
    inline int lowbit(int x){return x&-x;}
    void update(int &x,int l,int r,int pos,int v)
    {
    	if(!x)x=++p;s[x]+=v;if(l==r)return;
    	if(pos<=mid)update(lc[x],l,mid,pos,v);
    	else update(rc[x],mid+1,r,pos,v);
    }
    int query(int l,int r,int k)//树状数组的log个点暴力在线段树上跳
    {
    	if(l==r)return l;int sum=0;
    	for(int i=1;i<=cnt0;i++)sum+=s[lc[tmp[0][i]]];
    	for(int i=1;i<=cnt1;i++)sum-=s[lc[tmp[1][i]]];
    	if(k<=sum)
    	{
    		for(int i=1;i<=cnt0;i++)tmp[0][i]=lc[tmp[0][i]];
    		for(int i=1;i<=cnt1;i++)tmp[1][i]=lc[tmp[1][i]];
    		return query(l,mid,k);
    	}
    	else
    	{
    		for(int i=1;i<=cnt0;i++)tmp[0][i]=rc[tmp[0][i]];
    		for(int i=1;i<=cnt1;i++)tmp[1][i]=rc[tmp[1][i]];
    		return query(mid+1,r,k-sum);
    	}
    }
    void dfs(int u,int ff)
    {
    	fa[u][0]=ff;dep[u]=dep[ff]+1;dfn[u]=++tim;size[u]=1;
    	for(int i=1;i<=17;i++)fa[u][i]=fa[fa[u][i-1]][i-1];
    	for(int i=head[u];i;i=nxt[i])
    	{
    		int v=to[i];if(v==ff)continue;
    		dfs(v,u);size[u]+=size[v];
    	}
    }
    int getlca(int x,int y)
    {
    	if(dep[x]<dep[y])swap(x,y);
    	int tt=dep[x]-dep[y];
    	for(int i=0;i<=17;i++)
    		if(tt&(1<<i))x=fa[x][i];
    	if(x==y)return x;
    	for(int i=17;i>=0;i--)
    		if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
    	return fa[x][0];
    }
    void init()
    {
    	cin>>n>>Q;
    	for(int i=1;i<=n;i++)scanf("%d",&seq[i]),b[++tot]=seq[i];
    	for(int i=1,u,v;i<n;i++)scanf("%d%d",&u,&v),add(u,v),add(v,u);
    	for(int i=1;i<=Q;i++)
    	{
    		scanf("%d%d%d",&q[i].k,&q[i].a,&q[i].b);
    		if(!q[i].k)b[++tot]=q[i].b;
    	}
    	sort(b+1,b+1+tot);sz=unique(b+1,b+1+tot)-b-1;
    	for(int i=1;i<=n;i++)seq[i]=lower_bound(b+1,b+1+sz,seq[i])-b;
    	dfs(1,0);
    	for(int i=1;i<=n;i++)
    	{
    		for(int j=dfn[i];j<=n;j+=lowbit(j))
    			update(rt[j],1,sz,seq[i],1);
    		for(int j=dfn[i]+size[i];j<=n;j+=lowbit(j))
    			update(rt[j],1,sz,seq[i],-1);
    	}
    }
    int main()
    {
    	init();
    	for(int i=1,x,y;i<=Q;i++)
    	{
    		x=q[i].a;y=q[i].b;
    		if(q[i].k)
    		{
    			int lca=getlca(x,y),fl=fa[lca][0],len;cnt0=cnt1=0;
    			len=dep[x]+dep[y]-dep[lca]-dep[fl];
    			for(int j=dfn[x];j>=1;j-=lowbit(j))tmp[0][++cnt0]=rt[j];
    			for(int j=dfn[y];j>=1;j-=lowbit(j))tmp[0][++cnt0]=rt[j];
    			for(int j=dfn[lca];j>=1;j-=lowbit(j))tmp[1][++cnt1]=rt[j];
    			for(int j=dfn[fl];j>=1;j-=lowbit(j))tmp[1][++cnt1]=rt[j];
    			if(q[i].k>len)puts("invalid request!");
    			else printf("%d
    ",b[query(1,sz,len-q[i].k+1)]);
    			
    		}
    		else
    		{
    			for(int j=dfn[x];j<=n;j+=lowbit(j))
    				update(rt[j],1,sz,seq[x],-1);
    			for(int j=dfn[x]+size[x];j<=n;j+=lowbit(j))
    				update(rt[j],1,sz,seq[x],1);
    			seq[x]=lower_bound(b+1,b+1+sz,y)-b;
    			for(int j=dfn[x];j<=n;j+=lowbit(j))
    				update(rt[j],1,sz,seq[x],1);
    			for(int j=dfn[x]+size[x];j<=n;j+=lowbit(j))
    				update(rt[j],1,sz,seq[x],-1);
    		}
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    HRMSYS项目源码分析(二)
    HRMSYS项目源码分析(一)
    SQL类型转换以及自动在前面补0满足10位工号标示法
    android—资源文件(res)的引用
    SQL serve创建与调用存储过程
    .wsdl文件生成.cs文件
    android 文件操作类简易总结
    android EncodingUtils
    FTP创建与操作
    如何调试框架中的app
  • 原文地址:https://www.cnblogs.com/terribleterrible/p/9827550.html
Copyright © 2011-2022 走看看