P6035 Ryoku 的逆序对 (segment tree)

时间:2020-02-01 10:22:33   收藏:0   阅读:65

题目链接

技术图片

 

 

题解:

技术图片

 

 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\n", 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 }

 

评论(0
© 2014 mamicode.com 版权所有 京ICP备13008772号-2  联系我们:gaon5@hotmail.com
迷上了代码!