Remove Extra One 权值线段树

  最近疯狂练习线段树。。。

  这道题题意很简单,在1-n中,找寻一个数,使得去掉这个数后,对于每个位置中满足 1<=j<i && a[ j ]<a[ i ] 的位置尽可能多。

     我们考虑对于每个位置i的贡献,如果当前位置已经满足条件,那么前面任何数的删除,对这个位置实际上是没有贡献的,并且对于当前位置来说,删除这个位置相当于减去一个满足条件的位置。

     如果当前位置可以通过删除一个数,变成可能的话,那么这个数字一定在前i位置里,并且只有一个大于这个数的位置,我们可以轻松是查询前i位比某个值大的数目,以及查询最大值所处于的位置(一直往右查询即可)。那么i位置,要想成为答案,就必须删除前面的最大值,我们删除前面最大值,相当于增加一个满足条件的位置。

   如果前面有两个以上大于这个数,这个数肯定不能成为答案。

   所以我们维护一个数组,这个数组vis[i]代表删除i,可以生成新的满足条件位置个数,取最大值中,值最小的。就是答案!!!

  维护用权值线段树就可以啦!!!

  

  1 #include<iostream>
  2 #include<stdio.h>
  3 #include<string.h>
  4 #include<algorithm>
  5 #define LL long long
  6 #define lson rt<<1
  7 #define rson rt<<1|1
  8 #include<vector>
  9 using namespace std;
 10 const int maxx = 2e5+6;
 11 int vis[maxx];
 12 struct node{
 13   int l,r;
 14   int cnt;
 15 }tree[maxx<<2];
 16 int a[maxx];
 17 void buildtree(int rt,int l,int r){
 18    tree[rt].l=l;
 19    tree[rt].r=r;
 20    tree[rt].cnt=0;
 21    if(l==r){
 22      return ;
 23    }
 24    int mid=(l+r)>>1;
 25    buildtree(lson,l,mid);
 26    buildtree(rson,mid+1,r);
 27 }
 28 void update(int rt,int pos){
 29     int l=tree[rt].l;
 30     int r=tree[rt].r;
 31     if (l==r){
 32         tree[rt].cnt++;
 33         return;
 34     }
 35     int mid=(l+r)>>1;
 36     if(pos<=mid)
 37         update(lson,pos);
 38     else
 39         update(rson,pos);
 40     tree[rt].cnt=tree[lson].cnt+tree[rson].cnt;
 41 }
 42 int query_num(int rt,int w){
 43     int l=tree[rt].l;
 44     int r=tree[rt].r;
 45     if (l==r){
 46         return tree[rt].cnt;
 47     }
 48     int mid=(l+r)>>1;
 49     if(w<=mid){
 50         return tree[rson].cnt+query_num(lson,w);
 51     }else {
 52         return query_num(rson,w);
 53     }
 54 }
 55 int getmax(int rt){
 56     int l=tree[rt].l;
 57     int r=tree[rt].r;
 58     if(l==r){
 59         return l;
 60     }
 61     int mid=(l+r)>>1;
 62     if(tree[rson].cnt){
 63         return getmax(rson);
 64     }else {
 65         return getmax(lson);
 66     }
 67 }
 68 int main(){
 69    int n;
 70    while(~scanf("%d",&n)){
 71       for(int i=1;i<=n;i++){
 72         scanf("%d",&a[i]);
 73       }
 74       memset(vis,0,sizeof(vis));
 75       int mx=0;
 76       buildtree(1,1,n);
 77       for(int i=1;i<=n;i++){
 78          int s=query_num(1,a[i]);
 79          if(s==1){
 80             int pos=getmax(1);
 81             vis[pos]++;
 82          }else if(s==0){
 83             vis[a[i]]--;
 84          }
 85          update(1,a[i]);
 86       }
 87       int ans;
 88       mx=-2;
 89       for (int i=1;i<=n;i++){
 90           if(mx<vis[a[i]]){
 91             ans=a[i];
 92             mx=vis[a[i]];
 93           }
 94           else if(mx==vis[a[i]] && ans>a[i]){
 95             ans=a[i];
 96             mx=vis[a[i]];
 97           }
 98       }
 99        printf("%d\n",ans);
100    }
101    return 0;
102 }

 

   

posted @ 2019-08-30 00:18  bluefly-hrbust  阅读(228)  评论(0编辑  收藏  举报