标签:while sort names 涵盖 line getch 前缀和 16px work
这是你顾第一次写【树套树】!!!!!!!!
【原题】
求区间第k小元素,区间可修改
【正解】
如果没有修改的话,就直接写搞个主席树利用前缀和加加减减一下就好了。但是多了个修改,修改以为着从当前修改节点k到往后n-k个树顶所代表的树全部都要修改,这是一件非常操蛋的事情。回想起多年前学数据结构初步的时候,区间批量修改无非就是树状数组or线段树。故我们借用树状数组的轮廓来构建主席树的各树顶。
对树状数组每个节点,我们都当成是主席树的树顶,改树顶所涵盖的区间与树状数组该节点意义相同。
【查询】查询区间[l,r],先求出区间[1,l-1],再求出[1,r],至于求法嘛就跟树状数组那个lowbit一样,每次lowbit lowbit减下去就行了。
【修改】修改一个节点后,类于树状数组,将往后logn个节点都给改了就行。over
1 //copy by @ljq-despair 2 #include<bits/stdc++.h> 3 using namespace std; 4 inline int gi(){ 5 char a=getchar();int b=0; 6 while(a<‘0‘||a>‘9‘)a=getchar(); 7 while(a>=‘0‘&&a<=‘9‘)b=b*10+a-‘0‘,a=getchar(); 8 return b; 9 } 10 const int N=1e4+50; 11 struct node {int l,r,x;} t[N*900]; 12 struct ppp {int l,r,op,k;} b[N]; 13 int cmp(int* x,int* y) {return *x<*y;} 14 int a[N],p[N*5],n,m,tot1,tot2,lshh,cnt=1,root[N],root1[N],q1[N],q2[N]; int *lsh[N*5]; 15 void work(){ 16 sort(lsh+1,lsh+lshh+1,cmp);p[0]=-1; 17 for(int i=1,j=0;i<=lshh;++i) 18 { 19 if(*lsh[i]!=p[j])p[++j]=*lsh[i]; 20 *lsh[i]=j; 21 } 22 } 23 int modify(int l,int r,int x,int k,int o){ 24 int y=++cnt; 25 t[y]=t[x];t[y].x+=o; 26 if(l==r)return y; 27 int mid=(l+r)>>1; 28 if(k<=mid)t[y].l=modify(l,mid,t[x].l,k,o); 29 else t[y].r=modify(mid+1,r,t[x].r,k,o); 30 return y; 31 } 32 int query(int l,int r,int s1,int s2,int k){ 33 if(l==r)return l; 34 int x=t[t[s2].l].x-t[t[s1].l].x; 35 for(int i=1;i<=tot1;++i)x-=t[t[q1[i]].l].x; 36 for(int i=1;i<=tot2;++i)x+=t[t[q2[i]].l].x; 37 int mid=(l+r)>>1; 38 if(x>=k) 39 { 40 for(int i=1;i<=tot1;++i)q1[i]=t[q1[i]].l; 41 for(int i=1;i<=tot2;++i)q2[i]=t[q2[i]].l; 42 return query(l,mid,t[s1].l,t[s2].l,k); 43 } 44 else 45 { 46 for(int i=1;i<=tot1;++i)q1[i]=t[q1[i]].r; 47 for(int i=1;i<=tot2;++i)q2[i]=t[q2[i]].r; 48 return query(mid+1,r,t[s1].r,t[s2].r,k-x); 49 } 50 } 51 int main(){ 52 cin>>n>>m; 53 for(int i=1;i<=n;++i) 54 { 55 a[i]=gi(); 56 lsh[++lshh]=&a[i]; 57 } 58 for(int i=1;i<=m;++i) 59 { 60 char aa=getchar(); 61 while(!(aa==‘Q‘||aa==‘C‘))aa=getchar(); 62 b[i].l=gi(); 63 b[i].r=gi(); 64 if(aa==‘C‘) 65 { 66 b[i].op=1; 67 lsh[++lshh]=&b[i].r; 68 } 69 else b[i].k=gi(); 70 } 71 work(); 72 for(int i=1;i<=n;++i) 73 root1[i]=root[1]; 74 for(int i=1;i<=n;++i) 75 root[i]=modify(1,lshh,root[i-1],a[i],1); 76 for(int i=1;i<=m;++i) 77 if(b[i].op) 78 { 79 int x=b[i].l,y=b[i].r,s=a[x];a[x]=y; 80 while(x<=n) 81 { 82 root1[x]=modify(1,lshh,root1[x],s,-1); 83 root1[x]=modify(1,lshh,root1[x],y,1); 84 x+=(x&(-x)); 85 } 86 } 87 else 88 { 89 tot1=0,tot2=0;int x=b[i].l-1; 90 while(x){q1[++tot1]=root1[x];x-=(x&(-x));}x=b[i].r; 91 while(x){q2[++tot2]=root1[x];x-=(x&(-x));} 92 printf("%d\n",p[query(1,lshh,root[b[i].l-1],root[b[i].r],b[i].k)]); 93 } 94 return 0; 95 }
标签:while sort names 涵盖 line getch 前缀和 16px work
原文地址:https://www.cnblogs.com/Fung-JTY/p/9463693.html