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 }
有不懂欢迎咨询
QQ:1326487164(添加时记得备注)