P6035 Ryoku 的逆序对 (segment tree)
Posted feiief
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P6035 Ryoku 的逆序对 (segment tree)相关的知识,希望对你有一定的参考价值。
题解:
copy from: https://www.luogu.com.cn/blog/ryoku/ryoku-di-xin-nian-huan-le-sai-ti-xie
segment tree, seg[i]为区间元素个数,每次从剩下的数中找第(b[i]+1)小的数,然后去掉次数(seg[i]=0).
Code:
1 #include <bits/stdc++.h> 2 # define LL long long 3 using namespace std; 4 5 const int maxn=1000000+10; 6 const int mod=1E9+7; 7 int seg[maxn<<2]; 8 int n; 9 int b[maxn]; 10 11 void build(int idx, int left, int right){ 12 if(left==right){ 13 seg[idx]=1; 14 return; 15 } 16 17 int mid=(left+right)>>1; 18 build(idx<<1,left,mid); 19 build((idx<<1)+1,mid+1,right); 20 seg[idx]=seg[idx<<1]+seg[(idx<<1)+1]; 21 } 22 23 int findKth(int idx, int left, int right, int k){ 24 if(left==right) return left; 25 26 int size=seg[idx<<1]; 27 int mid=(left+right)>>1; 28 if(k<=size) return findKth(idx<<1,left,mid,k); 29 else return findKth((idx<<1)+1,mid+1,right,k-size); 30 } 31 32 void modify(int idx, int left, int right, int x){ 33 if(left==right){ 34 seg[idx]=0; 35 return; 36 } 37 int mid=(left+right)>>1; 38 if(x<=mid) modify(idx<<1,left,mid,x); 39 else modify((idx<<1)+1,mid+1,right,x); 40 seg[idx]=seg[idx<<1]+seg[(idx<<1)+1]; 41 } 42 43 int main(){ 44 scanf("%d", &n); 45 for(int i=1;i<=n;++i){ 46 scanf("%d", b+i); 47 } 48 LL ans=1; 49 for(int i=1;i<=n;++i){ 50 if(b[i]>n-i){ 51 printf("0"); 52 return 0; 53 } 54 if(b[i]==-1){ 55 ans=(ans*(n-i+1))%mod; 56 b[i]=0; 57 } 58 } 59 printf("%d ", ans); 60 build(1,1,n); 61 for(int i=1;i<=n;++i){ 62 int x=findKth(1,1,n,b[i]+1); 63 printf("%d ",x); 64 modify(1,1,n,x); 65 } 66 return 0; 67 }
以上是关于P6035 Ryoku 的逆序对 (segment tree)的主要内容,如果未能解决你的问题,请参考以下文章