zoukankan      html  css  js  c++  java
  • BZOJ1146 [CTSC2008]网络管理Network 树链剖分 主席树 树状数组

    欢迎访问~原文出处——博客园-zhouzhendong

    去博客园看该题解


    题目传送门 - BZOJ1146


    题意概括

      在一棵树上,每一个点一个权值。

      有两种操作:

      1、单点修改

      2、询问两点之间的树链上的第k大值


    题解

      水题。

      就是烦了一点。

      居然只调了3个小时?

      树链剖分+带修主席树。

      带修主席树:

      BZOJ1901 Zju2112 Dynamic Rankings 主席树


    代码

    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #include <cstdlib>
    #include <vector>
    using namespace std;
    const int N=80005;
    struct Gragh{
    	int cnt,y[N*2],nxt[N*2],fst[N];
    	void clear(){
    		cnt=0;
    		memset(fst,0,sizeof fst);
    	}
    	void add(int a,int b){
    		y[++cnt]=b,nxt[cnt]=fst[a],fst[a]=cnt;
    	}
    }g;
    struct cz{
    	int k,a,b;
    }q[N];
    int n,Q,v[N],Ha[N*2],hs;
    int fa[N],son[N],depth[N],size[N],top[N],p[N],ap[N],cnp=0;
    const int S=N*2*2*20;
    vector <int> val[N];
    int ls[S],rs[S],root[N],Next[S],sum[S],pp[S],app[S],tot=0,tpp=0;
    void LSH(){
    	sort(Ha+1,Ha+hs+1);
    	int hs_=1;
    	for (int i=2;i<=hs;i++)
    		if (Ha[i]!=Ha[i-1])
    			Ha[++hs_]=Ha[i];
    	hs=hs_;
    }
    void Get_Gen_Info(int rt,int pre,int d){
    	fa[rt]=pre,depth[rt]=d,size[rt]=1,son[rt]=-1;
    	for (int i=g.fst[rt];i;i=g.nxt[i])
    		if (g.y[i]!=pre){
    			int s=g.y[i];
    			Get_Gen_Info(s,rt,d+1);
    			size[rt]+=size[s];
    			if (son[rt]==-1||size[s]>size[son[rt]])
    				son[rt]=s;
    		}
    }
    void Get_Top(int rt,int tp){
    	top[rt]=tp;
    	ap[p[rt]=++cnp]=rt;
    	if (son[rt]==-1)
    		return;
    	Get_Top(son[rt],tp);
    	for (int i=g.fst[rt];i;i=g.nxt[i]){
    		int s=g.y[i];
    		if (s!=fa[rt]&&s!=son[rt])
    			Get_Top(s,s);
    	}
    }
    int find(int x){
    	return lower_bound(Ha+1,Ha+hs+1,x)-Ha;
    }
    void build(int &rt,int L,int R){
    	rt=++tot;
    	if (L==R){
    		ls[rt]=rs[rt]=0;
    		return;
    	}
    	int mid=(L+R)>>1;
    	build(ls[rt],L,mid);
    	build(rs[rt],mid+1,R);
    }
    void access(int prt,int &rt,int L,int R,int pos){
    	if (!rt||rt==prt)
    		rt=++tot;
    	Next[prt]=rt;
    	if (L==R)
    		return;
    	int mid=(L+R)>>1;
    	if (pos<=mid){
    		access(ls[prt],ls[rt],L,mid,pos);
    		if (!rs[rt])
    			rs[rt]=rs[prt];
    	}
    	else {
    		access(rs[prt],rs[rt],mid+1,R,pos);
    		if (!ls[rt])
    			ls[rt]=ls[prt];
    	}
    }
    void build_pp(int rt){
    	if (!rt)
    		return;
    	for (int i=rt;i;i=Next[i])
    		app[pp[i]=++tpp]=i;
    	build_pp(ls[rt]);
    	build_pp(rs[rt]);
    }
    int lowbit(int x){
    	return x&-x;
    }
    void add(int x,int d){
    	for (;x<=tpp;x+=lowbit(x))
    		sum[x]+=d;
    }
    int Sum(int x){
    	int ans=0;
    	for (;x>0;x-=lowbit(x))
    		ans+=sum[x];
    	return ans;
    }
    void update(int rt,int L,int R,int pos,int v){
    	add(pp[rt],v);
    	if (L==R)
    		return;
    	int mid=(L+R)>>1;
    	if (pos<=mid)
    		update(ls[rt],L,mid,pos,v);
    	else
    		update(rs[rt],mid+1,R,pos,v);
    }
    int query(int prt,int rt,int L,int R,int pos){
    	if (R<pos)
    		return 0;
    	if (L>=pos)
    		return Sum(pp[rt])-Sum(pp[prt]);
    	int mid=(L+R)>>1;
    	return query(ls[prt],ls[rt],L,mid,pos)+query(rs[prt],rs[rt],mid+1,R,pos);
    }
    int Tquery(int a,int b,int pos){
    	int f1=top[a],f2=top[b];
    	int total=0;
    	while (f1!=f2){
    		if (depth[f1]<depth[f2])
    			swap(f1,f2),swap(a,b);
    		total+=query(root[p[f1]-1],root[p[a]],1,hs,pos);
    		a=fa[f1],f1=top[a];
    	}
    	if (depth[a]>depth[b])
    		swap(a,b);
    	total+=query(root[p[a]-1],root[p[b]],1,hs,pos);
    	return total;
    }
    int main(){
    	scanf("%d%d",&n,&Q);
    	for (int i=1;i<=n;i++)
    		scanf("%d",&v[i]),Ha[i]=v[i];
    	hs=n;
    	g.clear();
    	for (int i=1,a,b;i<n;i++){
    		scanf("%d%d",&a,&b);
    		g.add(a,b);
    		g.add(b,a);
    	}
    	for (int i=1;i<=Q;i++){
    		scanf("%d%d%d",&q[i].k,&q[i].a,&q[i].b);
    		if (q[i].k==0)
    			Ha[++hs]=q[i].b;
    	}
    	LSH();
    	Get_Gen_Info(1,0,0);
    	Get_Top(1,1);
    	for (int i=1;i<=n;i++)
    		val[i].clear();
    	for (int i=1;i<=n;i++)
    		val[p[i]].push_back(find(v[i]));
    	for (int i=1;i<=Q;i++)
    		if (q[i].k==0)
    			val[p[q[i].a]].push_back(find(q[i].b));
    	build(root[0],1,hs);
    	memset(Next,0,sizeof Next);
    	for (int i=1;i<=n;i++)
    		for (int j=0;j<val[i].size();j++)
    			access(root[i-1],root[i],1,hs,val[i][j]);
    	build_pp(root[0]);
    	memset(sum,0,sizeof sum);
    	for (int i=1;i<=n;i++)
    		update(root[p[i]],1,hs,find(v[i]),1);
    	for (int i=1;i<=Q;i++){
    		if (q[i].k==0){
    			update(root[p[q[i].a]],1,hs,find(v[q[i].a]),-1);
    			update(root[p[q[i].a]],1,hs,find(v[q[i].a]=q[i].b),1);
    		}
    		else {
    			int L=1,R=hs,mid,ans=-1;
    			while (L<=R){
    				mid=(L+R)>>1;
    				if (Tquery(q[i].a,q[i].b,mid)>=q[i].k)
    					L=mid+1,ans=mid;
    				else
    					R=mid-1;
    			}
    			if (!~ans)
    				puts("invalid request!");
    			else
    				printf("%d
    ",Ha[ans]);
    		}
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    清除浮动的方法
    网页滚动到顶部或底部加载
    任意两个数之间的随机数
    每五个一行
    js放大镜
    HTML5本地存储
    jquery checkbox radio 标签 选中的3种方法
    jquery mouseout mouseover 多次执行
    CentOS6.5安装MySQL5.7(也适合其他版本安装)
    ubuntu下ganglia3.7.2编译安装
  • 原文地址:https://www.cnblogs.com/zhouzhendong/p/BZOJ1146.html
Copyright © 2011-2022 走看看