• 学习笔记(带修主席树)


    带修主席树
    • 感谢YMY大佬非常非常详细的口糊和debug(v.) ,首先主席树是离线算法。
    • 普通主席树是权值线段树,求区间里有几个数,就是用前缀和相减的方式。
    • 其实带修主席树也大同小异。
    算法实现
    • 首先你需要离线所有的操作,主要是要将修改之后的值也离散进取
    • 对于每次修改,用树状数组的方式每次加lowbit(),对每个点都insert一下。
    • 对于每次询问,先开两个数组,将左右端点树状数组的跳的点都存下来,每次查询区间都用所用又端点减所有左端点,进左右子树时,也要将这些点换成左右子树。

    洛谷 Dynamic Ranking

    #include<bits/stdc++.h>
    using namespace std;
    typedef int sign;
    typedef long long ll;
    #define For(i,a,b) for(register sign i=(sign)a;i<=(sign)b;++i)
    #define Fordown(i,a,b) for(register sign i=(sign)a;i>=(sign)b;--i)
    const int N=1e4+5;
    bool cmax(sign &a,sign b){return (a<b)?a=b,1:0;}
    bool cmin(sign &a,sign b){return (a>b)?a=b,1:0;}
    template<typename T>T read()
    {
    	T ans=0,f=1;
    	char ch=getchar();
    	while(!isdigit(ch)&&ch!='-')ch=getchar();
    	if(ch=='-')f=-1,ch=getchar();
    	while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch-'0'),ch=getchar();
    	return ans*f;
    }
    template<typename T>void write(T x,char y)
    {
    	if(x==0)
    	{
    		putchar('0');putchar(y);
    		return;
    	}
    	if(x<0)
    	{
    		putchar('-');
    		x=-x;
    	}
    	static char wr[20];
    	int top=0;
    	for(;x;x/=10)wr[++top]=x%10+'0';
    	while(top)putchar(wr[top--]);
    	putchar(y);
    }
    void file()
    {
    	#ifndef ONLINE_JUDGE
    		freopen("2617.in","r",stdin);
    		freopen("2617.out","w",stdout); 
    #endif 
    } 
    int n,m;
    int size,cnt,rt[N*200],ls[N*200],rs[N*200],sz[N*200];
    int a[N],b[N<<1];
    int opt[N][5];
    void input()
    {
    	n=read<int>();m=read<int>();
    	For(i,1,n)a[i]=b[i]=read<int>();
    	size=n;
    	char s[10];
    	For(i,1,m)
    	{
    		scanf("%s",s);
    		opt[i][1]=read<int>();opt[i][2]=read<int>();
    		if(s[0]=='Q')opt[i][0]=1,opt[i][3]=read<int>();	
    		else if(s[0]=='C')opt[i][0]=2,b[++size]=opt[i][2];
    	}
    }
    #define mid ((l+r)>>1)
    void insert(int &h,int pre,int l,int r,int pos,int v)
    {
    	h=++cnt;ls[h]=ls[pre];rs[h]=rs[pre];sz[h]=sz[pre]+v;
    	if(l==r)return;
    	if(pos<=mid)insert(ls[h],ls[pre],l,mid,pos,v);
    	else insert(rs[h],rs[pre],mid+1,r,pos,v);
    }
    void add(int pos,int v)
    {
    	int k=lower_bound(b+1,b+size+1,a[pos])-b;
    	for(;pos<=n;pos+=pos&-pos)insert(rt[pos],rt[pos],1,size,k,v);
    }
    void init()
    {
    	sort(b+1,b+size+1);
    	size=unique(b+1,b+size+1)-(b+1);
    	For(i,1,n)add(i,1);
    }
    int lef[N],rig[N],tr,tl;
    int query(int l,int r,int k)
    {
    	if(l==r)return mid;
    	static int sum;
    	sum=0;
    	For(i,1,tl)sum-=sz[ls[lef[i]]];
    	For(i,1,tr)sum+=sz[ls[rig[i]]];
    	if(sum>=k)
    	{
    		For(i,1,tl)lef[i]=ls[lef[i]];
    		For(i,1,tr)rig[i]=ls[rig[i]];
    		return query(l,mid,k);
    	}
    	else 
    	{
    		For(i,1,tl)lef[i]=rs[lef[i]];
    		For(i,1,tr)rig[i]=rs[rig[i]];
    		return query(mid+1,r,k-sum);
    	}
    }
    void work()
    {
    	For(i,1,m)
    	{
    		if(opt[i][0]==1)
    		{
    			tl=tr=0;
    			for(register int j=opt[i][1]-1;j;j-=j&-j)lef[++tl]=rt[j];
    			for(register int j=opt[i][2];j;j-=j&-j)rig[++tr]=rt[j];
    			write(b[query(1,size,opt[i][3])],'
    ');
    		}
    		else if(opt[i][0]==2)
    		{
    			add(opt[i][1],-1);
    			a[opt[i][1]]=opt[i][2];
    			add(opt[i][1],1);
    		}
    	}
    }
    int main()
    {
    	file();
    	input();
    	init();
    	work();
    	return 0;
    }
    

    洛谷 Count on a tree

    #include<bits/stdc++.h>
    using namespace std;
    typedef int sign;
    typedef long long ll;
    #define For(i,a,b) for(register sign i=(sign)a;i<=(sign)b;++i)
    #define Fordown(i,a,b) for(register sign i=(sign)a;i>=(sign)b;--i)
    const int N=1e5+5;
    bool cmax(sign &a,sign b){return (a<b)?a=b,1:0;}
    bool cmin(sign &a,sign b){return (a>b)?a=b,1:0;}
    template<typename T>T read()
    {
    	T ans=0,f=1;
    	char ch=getchar();
    	while(!isdigit(ch)&&ch!='-')ch=getchar();
    	if(ch=='-')f=-1,ch=getchar();
    	while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch-'0'),ch=getchar();
    	return ans*f;
    }
    template<typename T>void write(T x,char y)
    {
    	if(x==0)
    	{
    		putchar('0');putchar(y);
    		return;
    	}
    	if(x<0)
    	{
    		putchar('-');
    		x=-x;
    	}
    	static char wr[20];
    	int top=0;
    	for(;x;x/=10)wr[++top]=x%10+'0';
    	while(top)putchar(wr[top--]);
    	putchar(y);
    }
    void file()
    {
    	#ifndef ONLINE_JUDGE
    		freopen("2633.in","r",stdin);
    		freopen("2633.out","w",stdout);
    	#endif
    }
    int n,m;
    int a[N],b[N];
    struct edge
    {
    	int v,nex;
    }e[N<<1];
    int head[N],tt;
    void add(int x,int y){++tt;e[tt].v=y;e[tt].nex=head[x];head[x]=tt;}
    void input()
    {
    	int x,y;
    	n=read<int>();m=read<int>();
    	For(i,1,n)a[i]=b[i]=read<int>();
    	For(i,1,n-1)
    	{
    		x=read<int>();y=read<int>();
    		add(x,y);add(y,x);
    	}
    }
    int top[N],dep[N],son[N],fa[N],size[N],id[N],order[N],dfs_clock;
    int rt[N<<6],ls[N<<6],rs[N<<6],sum[N<<6],sz,cnt;
    void dfs1(int u,int pre)
    {
    	dep[u]=dep[pre]+1;fa[u]=pre;size[u]=1;
    	int v;
    	for(register int i=head[u];i;i=e[i].nex)
    	{
    		v=e[i].v;
    		if(v^pre)
    		{
    			dfs1(v,u);
    			size[u]+=size[v];
    			if(size[son[u]]<size[v])son[u]=v;
    		}
    	}
    }
    void dfs2(int u,int start)
    {
    	top[u]=start;id[u]=++dfs_clock;order[dfs_clock]=u;
    	if(!son[u])return;
    	dfs2(son[u],start);
    	int v;
    	for(register int i=head[u];i;i=e[i].nex)
    	{
    		v=e[i].v;
    		if(v^fa[u]&&v^son[u])dfs2(v,v);
    	}
    }
    #define mid ((l+r)>>1)
    void build(int &h,int l,int r)
    {
    	h=++cnt;
    	if(l==r)return;
    	build(ls[h],l,mid);build(rs[h],mid+1,r);
    }
    void insert(int &h,int pre,int l,int r,int pos)
    {
    	h=++cnt;ls[h]=ls[pre];rs[h]=rs[pre];sum[h]=sum[pre]+1;
    	if(l==r)return;
    	if(pos<=mid)insert(ls[h],ls[pre],l,mid,pos);
    	else insert(rs[h],rs[pre],mid+1,r,pos);
    }
    void init()
    {
    	sort(b+1,b+n+1);
    	sz=unique(b+1,b+n+1)-(b+1);
    	build(rt[0],1,sz);
    	For(i,1,n)insert(rt[i],rt[i-1],1,sz,lower_bound(b+1,b+sz+1,a[order[i]])-b);
    }
    int lans;
    int tl,tr,lef[N],rig[N];
    void query_tree(int x,int y)
    {
    	tl=tr=0;
    	int tx=top[x],ty=top[y];
    	while(tx^ty)
    	{
    		if(dep[tx]<dep[ty])swap(tx,ty),swap(x,y);
    		lef[++tl]=rt[id[tx]-1];rig[++tr]=rt[id[x]];
    		x=fa[tx];tx=top[x];
    	}
    	if(dep[x]>dep[y])swap(x,y);
    	lef[++tl]=rt[id[x]-1];rig[++tr]=rt[id[y]];
    }
    int query(int l,int r,int k)
    {
    	if(l==r)return l;
    	static int num;num=0;
    	For(i,1,tl)num-=sum[ls[lef[i]]];
    	For(i,1,tr)num+=sum[ls[rig[i]]];
    	if(num>=k)
    	{
    		For(i,1,tl)lef[i]=ls[lef[i]];
    		For(i,1,tr)rig[i]=ls[rig[i]];
    		return query(l,mid,k);
    	}
    	else
    	{
    		For(i,1,tl)lef[i]=rs[lef[i]];
    		For(i,1,tr)rig[i]=rs[rig[i]];
    		return query(mid+1,r,k-num);
    	}
    }
    void work()
    {
    	int u,v,k;
    	For(i,1,m)
    	{
    		u=read<int>()^lans;v=read<int>();k=read<int>();
    		query_tree(u,v);
    		lans=b[query(1,sz,k)];
    		printf("%d
    ",lans);
    	}
    }
    int main()
    {
    	file();
    	input();
    	dfs1(1,0);
    	dfs2(1,1);
    	init();
    	work();
    	return 0;
    }
    

    洛谷3175动态逆序对

    // luogu-judger-enable-o2
    // luogu-judger-enable-o2
    #include<bits/stdc++.h>
    using namespace std;
    typedef int sign;
    typedef long long ll;
    #define For(i,a,b) for(register sign i=(sign)a;i<=(sign)b;++i)
    #define Fordown(i,a,b) for(register sign i=(sign)a;i>=(sign)b;--i)
    const int N=2e5+5;
    bool cmax(sign &a,sign b){return (a<b)?a=b,1:0;}
    bool cmin(sign &a,sign b){return (a>b)?a=b,1:0;}
    template<typename T>T read()
    {
        T ans=0,f=1;
        char ch=getchar();
        while(!isdigit(ch)&&ch!='-')ch=getchar();
        if(ch=='-')f=-1,ch=getchar();
        while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch-'0'),ch=getchar();
        return ans*f;
    }
    template<typename T>void write(T x,char y)
    {
        if(x==0)
        {
            putchar('0');putchar(y);
            return;
        }
        if(x<0)
        {
            putchar('-');
            x=-x;
        }
        static char wr[20];
        int top=0;
        for(;x;x/=10)wr[++top]=x%10+'0';
        while(top)putchar(wr[top--]);
        putchar(y);
    }
    void file()
    {
        #ifndef ONLINE_JUDGE
            freopen("3157.in","r",stdin);
            freopen("3157.out","w",stdout);
        #endif
    }
    int n,m;
    int a[N],p[N];
    void input()
    {
        n=read<int>();m=read<int>();
        For(i,1,n)
        {
            a[i]=read<int>();
            p[a[i]]=i;
        }
    }
    int rt[N],ls[N<<6],rs[N<<6],sum[N<<6],cnt;
    int tl,tr,lef[N],rig[N];
    #define mid ((l+r)>>1)
    #define sz n
    void insert(int &h,int pre,int l,int r,int pos,int v)
    {
        h=++cnt;ls[h]=ls[pre];rs[h]=rs[pre];sum[h]=sum[pre]+v;
        if(l==r)return;
        if(pos<=mid)insert(ls[h],ls[pre],l,mid,pos,v);
        else insert(rs[h],rs[pre],mid+1,r,pos,v);
    }
    void add(int pos,int v)
    {
        int k=a[pos];
        for(;pos<=n;pos+=pos&-pos)insert(rt[pos],rt[pos],1,sz,k,v);
    }
    ll ans;
    int c[N];
    int num1[N],num2[N];
    int get_sum(int x)
    {
        int res=0;
        for(;x;x-=x&-x)res+=c[x];
        return res;
    }
    void add_sum(int x,int v)
    {
        for(;x<=n;x+=x&-x)c[x]+=v;
    }
    void cal()
    {
        For(i,1,n)
        {
            num1[i]=get_sum(n)-get_sum(a[i]);
            ans+=num1[i];
            add_sum(a[i],1);
        }
        memset(c,0,sizeof c);
        Fordown(i,n,1)
        {
            num2[i]=get_sum(a[i]-1);
            add_sum(a[i],1);
        }
    }
    void get(int x,int y)
    {
        tl=tr=0;
        for(int i=x;i;i-=i&-i)lef[++tl]=rt[i];
        for(int i=y;i;i-=i&-i)rig[++tr]=rt[i];
    }
    void turl()
    {
        For(i,1,tl)lef[i]=ls[lef[i]];
        For(i,1,tr)rig[i]=ls[rig[i]];
    }
    void turr()
    {
        For(i,1,tl)lef[i]=rs[lef[i]];
        For(i,1,tr)rig[i]=rs[rig[i]];
    }
    int querypre(int x,int y,int v)
    {
    	if(x>y)return 0;
        get(x-1,y);
        int l=1,r=sz,res=0;
        while(l^r)
        {
            if(v<=mid)
            {
                For(i,1,tl)res-=sum[rs[lef[i]]];
                For(i,1,tr)res+=sum[rs[rig[i]]];
                turl();
                r=mid;
            }
            else
            {
                turr();
                l=mid+1;
            }
        }
        return res;
    }
    int querynex(int x,int y,int v)
    {
    	if(x>y)return 0;
        get(x-1,y);
        int l=1,r=sz,res=0;
        while(l^r)
        {
            if(v>mid)
            {
                For(i,1,tl)res-=sum[ls[lef[i]]];
                For(i,1,tr)res+=sum[ls[rig[i]]];
                turr();
                l=mid+1;
            }
            else
            {
                turl();
                r=mid;
            }
        }
        return res;
    }
    void work()
    {
        int x;
        For(i,1,m)
        {
            x=read<int>();
            write(ans,'
    ');
            x=p[x];
            ans=ans-(num1[x]+num2[x]-querypre(1,x-1,a[x])-querynex(x+1,n,a[x]));
            add(x,1);
        }
    }
    int main()
    {
        file();
        input();
        cal();
        work();
        return 0;
    }
    
  • 相关阅读:
    c_hhc_互补二元组(延迟计数+简单公式变换)
    b_vj_Hamiltonian Cycle(记忆化+位运算各种技巧)
    b_lq_分考场(尽量安排到旧考场)
    线程停止
    Lambda表达式
    静态代理演示
    多线程模拟龟兔赛跑
    Runnable和Thread
    线程网图下载
    接口
  • 原文地址:https://www.cnblogs.com/dengyixuan/p/8261051.html
Copyright © 2020-2023  润新知