1. 程式人生 > >洛谷P4364 [九省聯考2018]IIIDX(線段樹)

洛谷P4364 [九省聯考2018]IIIDX(線段樹)

its pre bool span sin += pac 註意 digi

傳送門

題解看得……很……迷?

因為取完一個數後,它的子樹中只能取權值小於等於它的數。我們先把權值從大到小排序,然後記$a_i$為他左邊(包括自己)所有取完他還能取的數的個數。那麽當取完一個點$x$的數之後,我們需要為它子樹中的點預留出權值,這些權值肯定在它的左邊。但我們不知道它子樹中的數會取哪幾個數,所以我們就把$x$及其右邊的數的$a_i$全都減去$x$的子樹大小$size_x$,那麽就代表$x$的左邊有這麽多位置被占據了。那麽某一個點$y$要取值的時候,我們只要在線段樹上找到最左邊的一個點,滿足它右邊(包括自己)所有的$a_i$都大於等於當前子樹的$size$即可,這個在線段樹上二分就可以了

然後要註意,父親給他們預留出了權值,那麽在做到兒子的時候把這些預留的空間取出來,也就是把上面的影響消除。父親只給兒子預留了一次空間,所以消除影響也只需要一次就夠了

 1 //minamoto
 2 #include<bits/stdc++.h>
 3 using namespace std;
 4 inline int read(){
 5     #define num ch-‘0‘
 6     char ch;bool flag=0;int res;
 7     while(!isdigit(ch=getchar()))
 8     (ch==-)&&(flag=true
); 9 for(res=num;isdigit(ch=getchar());res=res*10+num); 10 (flag)&&(res=-res); 11 #undef num 12 return res; 13 } 14 const int N=5e5+5; 15 int mn[N<<2],tag[N<<2]; 16 int n;double k; 17 int a[N],ans[N],sz[N],fa[N],cnt[N]; 18 inline bool cmp(int a,int b){return
a>b;} 19 #define ls (p<<1) 20 #define rs (p<<1|1) 21 inline void upd(int p){mn[p]=min(mn[ls],mn[rs]);} 22 inline void ppd(int p,int t){mn[p]+=t,tag[p]+=t;} 23 inline void pd(int p){ppd(ls,tag[p]),ppd(rs,tag[p]),tag[p]=0;} 24 void build(int p,int l,int r){ 25 if(l==r) return (void)(mn[p]=l); 26 int mid=(l+r)>>1; 27 build(ls,l,mid),build(rs,mid+1,r),upd(p); 28 } 29 int query(int p,int l,int r,int k){ 30 if(l==r) return mn[p]>=k?l:l+1; 31 int mid=(l+r)>>1;if(tag[p]) pd(p); 32 return k<=mn[rs]?query(ls,l,mid,k):query(rs,mid+1,r,k); 33 } 34 void update(int p,int l,int r,int ql,int qr,int k){ 35 if(ql<=l&&qr>=r) return (void)(ppd(p,k)); 36 int mid=(l+r)>>1;if(tag[p]) pd(p); 37 if(ql<=mid) update(ls,l,mid,ql,qr,k); 38 if(qr>mid) update(rs,mid+1,r,ql,qr,k); 39 upd(p); 40 } 41 int main(){ 42 // freopen("testdata.in","r",stdin); 43 n=read();scanf("%lf",&k); 44 for(int i=1;i<=n;++i) a[i]=read(); 45 sort(a+1,a+1+n,cmp); 46 for(int i=n-1;i;--i) 47 cnt[i]=a[i]==a[i+1]?cnt[i+1]+1:0; 48 for(int i=1;i<=n;++i) fa[i]=(int)(i/k),sz[i]=1; 49 for(int i=n;i;--i) sz[fa[i]]+=sz[i]; 50 build(1,1,n); 51 for(int i=1;i<=n;++i){ 52 if(fa[i]&&fa[i]!=fa[i-1]) update(1,1,n,ans[fa[i]],n,sz[fa[i]]-1); 53 int x=query(1,1,n,sz[i]); 54 x+=cnt[x],++cnt[x],x-=(cnt[x]-1);ans[i]=x; 55 update(1,1,n,x,n,-sz[i]); 56 } 57 for(int i=1;i<=n;++i) printf("%d ",a[ans[i]]); 58 return 0; 59 }

洛谷P4364 [九省聯考2018]IIIDX(線段樹)