• 【SYZOJ279】滑稽♂树(树套树)


    【SYZOJ279】滑稽♂树(树套树)

    题面

    SYZOJ
    CJOJ

    题目描述

    zzsyz实验楼里面种了一棵滑稽树,只有滑稽之力达到大乘期的oier才能看到。虽然我们看不到,但是还是知道一些信息:

    这真的是一棵树,由n个节点,n-1条边联通。一号滑稽果同时也是整棵滑稽树的树根。

    滑稽树上每个节点有一个滑稽果,每个滑稽果有它的重量。

    雪甜甜公主是神犇当然看得到那棵滑稽树啦,现在她感兴趣的是这样三件事

    1:滑稽树太大啦,雪甜甜公主有的时候只想知道,在以某一个滑稽果为根的子滑稽树里面,重量第k小的果子的重量是多少?

    2:除了重量第k小的果子,雪甜甜还想知道以某个滑稽果为根的子滑稽树里面,重量在[a, b]这个范围内的滑稽果有多少个。

    3:雪甜甜还喜欢吃滑稽果,但是吃完,原来滑稽果的位置上还会长出一个新的滑稽果,只是重量可能不一样。
    输入格式

    第一行一个正整数n,表示滑稽树有n个节点。

    第二行n个正整数,分别描述1号,2号,,,,n号节点滑稽果的重量。

    接下来n-1行,每行2个正整数u, v ∈ [1, n],表示滑稽果u与滑稽果v之间有树枝连接。

    接下来一个正整数q,表示雪甜甜有q次行动

    之后q行,有这样3种形式

    1 u k 雪甜甜公主询问以u为根的子滑稽树中,重量第k小的滑稽果的重量。

    2 u a b 雪甜甜公主想知道,以u为根的子滑稽树中,重量在[a, b]范围内的滑稽果有多少个。

    3 u x 雪甜甜公主吃掉了编号为u的滑稽果,但是在原位置上立刻长出来了一个重量为x的滑稽果。因为位置没有变,所以编号还是u。
    输出格式

    对于每次询问,输出结果。

    样例

    input

    5
    3 4 6 1 2
    1 2
    1 3
    3 4
    3 5
    7
    1 1 4
    2 1 1 5
    3 4 5
    1 1 4
    2 3 3 6
    3 5 7
    1 3 3

    output

    4
    4
    5
    2
    7

    题解

    树套树大裸题
    直接来一个带修改主席树就没了
    真简单

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<set>
    #include<map>
    #include<vector>
    #include<queue>
    using namespace std;
    #define ll long long
    #define RG register
    #define MAX 55555
    inline int read()
    {
        RG int x=0,t=1;RG char ch=getchar();
        while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
        if(ch=='-')t=-1,ch=getchar();
        while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
        return x*t;
    }
    int n,W[MAX];
    struct Line{int v,next;}e[MAX<<1];
    int h[MAX],cnt=1;
    inline void Add(int u,int v){e[cnt]=(Line){v,h[u]};h[u]=cnt++;}
    int dfn[MAX],low[MAX],tim;
    void dfs(int u,int ff)
    {
    	dfn[u]=++tim;
    	for(int i=h[u];i;i=e[i].next)
    		if(e[i].v!=ff)dfs(e[i].v,u);
    	low[u]=tim;
    }
    int rt[MAX],tot;
    struct Node{int ls,rs,v;}t[MAX<<7];
    int lb(int x){return x&(-x);}
    void Modify(int &x,int ff,int l,int r,int p,int w)
    {
    	x=++tot;t[x]=t[ff];t[x].v+=w;
    	if(l==r)return;
    	int mid=(l+r)>>1;
    	if(p<=mid)Modify(t[x].ls,t[ff].ls,l,mid,p,w);
    	else Modify(t[x].rs,t[ff].rs,mid+1,r,p,w);
    }
    void preModify(int x,int p,int w)
    {
    	for(int i=x;i<=n;i+=lb(i))
    		Modify(rt[i],rt[i],1,10000,p,w);
    }
    int tmp1[MAX],tmp2[MAX],t1,t2;
    void preQuery(int l,int r)
    {
    	t1=t2=0;
    	for(int i=l;i;i-=lb(i))tmp1[++t1]=rt[i];
    	for(int i=r;i;i-=lb(i))tmp2[++t2]=rt[i];
    }
    int Query(int l,int r,int K)
    {
    	if(l==r)return l;
    	int s=0,mid=(l+r)>>1;
    	for(int i=1;i<=t1;++i)s-=t[t[tmp1[i]].ls].v;
    	for(int i=1;i<=t2;++i)s+=t[t[tmp2[i]].ls].v;
    	if(s>=K)
    	{
    		for(int i=1;i<=t1;++i)tmp1[i]=t[tmp1[i]].ls;
    		for(int i=1;i<=t2;++i)tmp2[i]=t[tmp2[i]].ls;
    		return Query(l,mid,K);
    	}
    	else
    	{
    		for(int i=1;i<=t1;++i)tmp1[i]=t[tmp1[i]].rs;
    		for(int i=1;i<=t2;++i)tmp2[i]=t[tmp2[i]].rs;
    		return Query(mid+1,r,K-s);
    	}
    }
    int QuerySum(int l,int r,int L,int R)
    {
    	int ret=0;
    	if(L<=l&&r<=R)
    	{
    		for(int i=1;i<=t1;++i)ret-=t[tmp1[i]].v;
    		for(int i=1;i<=t2;++i)ret+=t[tmp2[i]].v;
    		return ret;
    	}
    	int mid=(l+r)>>1;
    	if(L<=mid)
    	{
    		int T1[MAX],T2[MAX];
    		for(int i=1;i<=t1;++i)T1[i]=tmp1[i],tmp1[i]=t[tmp1[i]].ls;
    		for(int i=1;i<=t2;++i)T2[i]=tmp2[i],tmp2[i]=t[tmp2[i]].ls;
    		ret+=QuerySum(l,mid,L,R);
    		for(int i=1;i<=t1;++i)tmp1[i]=T1[i];
    		for(int i=1;i<=t2;++i)tmp2[i]=T2[i];
    	}
    	if(R>mid)
    	{
    		int T1[MAX],T2[MAX];
    		for(int i=1;i<=t1;++i)T1[i]=tmp1[i],tmp1[i]=t[tmp1[i]].rs;
    		for(int i=1;i<=t2;++i)T2[i]=tmp2[i],tmp2[i]=t[tmp2[i]].rs;
    		ret+=QuerySum(mid+1,r,L,R);
    		for(int i=1;i<=t1;++i)tmp1[i]=T1[i];
    		for(int i=1;i<=t2;++i)tmp2[i]=T2[i];
    	}
    	return ret;
    }
    int main()
    {
    	n=read();
    	for(int i=1;i<=n;++i)W[i]=read();
    	for(int i=1;i<n;++i)
    	{
    		int u=read(),v=read();
    		Add(u,v);Add(v,u);
    	}
    	dfs(1,0);
    	for(int i=1;i<=n;++i)
    		preModify(dfn[i],W[i],1);
    	int Q=read();
    	while(Q--)
    	{
    		int opt=read(),u=read();
    		if(opt==1)
    		{
    			preQuery(dfn[u]-1,low[u]);
    			printf("%d
    ",Query(1,10000,read()));
    		}
    		if(opt==2)
    		{
    			int l=read(),r=read();
    			preQuery(dfn[u]-1,low[u]);
    			printf("%d
    ",QuerySum(1,10000,l,r));
    		}
    		if(opt==3)
    		{
    			preModify(dfn[u],W[u],-1);
    			W[u]=read();
    			preModify(dfn[u],W[u],1);
    		}
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    Nginx02 Nginx的的目录结构、基本工作原理、基本配置文件介绍
    正向代理和反向代理
    Nginx 05 动静分离
    Nginx06 Rewrite
    Nginx07 keepalived
    Nginx01 简介和安装
    负载均衡
    Nginx04 反向代理和负载均衡
    VM安装Centos 经典安装
    linux CentOS7安装MySQL8.0.28
  • 原文地址:https://www.cnblogs.com/cjyyb/p/8562604.html
Copyright © 2020-2023  润新知