• 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;
    }
    

      

  • 相关阅读:
    PAT 解题报告 1009. Product of Polynomials (25)
    PAT 解题报告 1007. Maximum Subsequence Sum (25)
    PAT 解题报告 1003. Emergency (25)
    PAT 解题报告 1004. Counting Leaves (30)
    【转】DataSource高级应用
    tomcat下jndi配置
    java中DriverManager跟DataSource获取getConnection有什么不同?
    理解JDBC和JNDI
    JDBC
    Dive into python 实例学python (2) —— 自省,apihelper
  • 原文地址:https://www.cnblogs.com/zhouzhendong/p/BZOJ1146.html
Copyright © 2020-2023  润新知