Codeforces Global Round 7E(线段树,贪心)

 1 #define HAVE_STRUCT_TIMESPEC
 2 #include<bits/stdc++.h>
 3 using namespace std;
 4 long long a[300007],q[300007],b[300007];
 5 long long mx[1200007],mxid[1200007];
 6 long long lz[1200007];
 7 void up(long long rt){
 8     if(mx[rt<<1]>=mx[rt<<1|1]){
 9         mx[rt]=mx[rt<<1];
10         mxid[rt]=mxid[rt<<1];
11     }
12     else{
13         mx[rt]=mx[rt<<1|1];
14         mxid[rt]=mxid[rt<<1|1];
15     }
16 }
17 void down(long long rt){
18     lz[rt<<1]+=lz[rt];
19     lz[rt<<1|1]+=lz[rt];
20     mx[rt<<1]+=lz[rt];
21     mx[rt<<1|1]+=lz[rt];
22     lz[rt]=0;
23 }
24 void build(long long rt,long long l,long long r){
25     if(l==r){
26         mx[rt]=0;
27         mxid[rt]=l;
28         return ;
29     }
30     build(rt<<1,l,(l+r)>>1);
31     build(rt<<1|1,((l+r)>>1)+1,r);
32     up(rt);
33 }
34 void update(long long rt,long long l,long long r,long long L,long long R,long long k){
35     if(L>R)
36         return ;
37     if(L<=l&&r<=R){
38         lz[rt]+=k;
39         mx[rt]+=k;
40         return ;
41     }
42     down(rt);
43     if(L<=((l+r)>>1))
44         update(rt<<1,l,(l+r)>>1,L,R,k);
45     if(R>((l+r)>>1))
46         update(rt<<1|1,((l+r)>>1)+1,r,L,R,k);
47     up(rt);
48 }
49 long long cmx,cid;
50 void query(long long rt,long long l,long long r,long long L,long long R){
51     if(L<=l&&r<=R){
52         if(mx[rt]>cmx){
53             cmx=mx[rt];
54             cid=mxid[rt];
55         }
56         return ;
57     }
58     down(rt);
59     if(L<=((l+r)>>1))
60         query(rt<<1,l,(l+r)>>1,L,R);
61     if(R>((l+r)>>1))
62         query(rt<<1|1,((l+r)>>1)+1,r,L,R);
63 }
64 int main(){
65     ios::sync_with_stdio(false);
66     cin.tie(NULL);
67     cout.tie(NULL);
68     int n;
69     cin>>n;
70     for(int i=1;i<=n;++i){
71         cin>>a[i];
72         b[a[i]]=i;//存放每个数出现的位置
73     }
74     for(int i=1;i<=n;++i)
75         cin>>q[i];
76     build(1,1,n);
77     int ans=n;
78     update(1,1,n,1,b[n],1);//最大值出现的位置以及左边全部+1,意为这些位置及右侧有一个数不比它们小(此时还没有加入炸弹)
79     for(int i=1;i<=n;++i){
80         cout<<ans<<" ";
81         update(1,1,n,1,q[i],-1);//每次加入一个炸弹,在炸弹位置及左侧全部-1,如果所有点都不为正值,说明当前ans非法,因为所有大于等于它的数位置及其右侧都有至少x颗炸弹(x为这个数是第几大的数)
82         while(mx[1]<=0){
83             --ans;//答案-1,重新检测是否合法
84             update(1,1,n,1,b[ans],1);//-1以后所有ans及其左侧的数位置及其右侧都多了一个不比自己小的数
85         }
86     }
87     return 0;
88 }

猜你喜欢

转载自www.cnblogs.com/ldudxy/p/12554901.html