带修主席树
- 感谢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])],'\n'); } 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\n",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,'\n'); 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; }
来源:https://www.cnblogs.com/dengyixuan/p/8261051.html