[Codeforces773E] [线段树] [找规律] Blog Post Rating

来源:互联网 发布:淘宝首页图片大小 编辑:程序博客网 时间:2024/05/18 01:29

题意大概是
有一个博客,初始赞数为0,每个人会浏览这篇博客,如果这个人期望的赞数大于这边博客的赞数,他就会赞这篇博客,如果小于这篇博客,就踩一下(博客赞数-1),相同就不操作。询问对于每个i,1~i的人按照一个顺序浏览,求一种顺序使得博客最后的赞数最大,输出这个最大的赞数。

先瞎猜一下,这1~i个人肯定是按照期望的赞数升序访问最优。
然后写个暴力交一下,发现T了,说明这个结论是对的

那么只要维护一下这个序列就可以了。可以用权值线段树维护。
考虑怎么求这个按照这个升序顺序访问能得到的答案。

首先aiai是当前排序后的数列中的第i个,不是原始数列的)是可能有负数的,那么肯定存在某个x,使ax<=x,那么在x的位置,博客的赞数为x,从x+1开始,博客的赞数就会单调不减。
f(i)表示在i位置博客的赞数,那么f(i)=min(f(i1)+1,ai)
展开展开展开发现一个区间[l,r] ,长度为k
f(r)=min(f(l1)+k,al+k1,al+1+k2,......,ar1+1,ar)

那么每个区间维护一下min(al+k1,al+1+k2,......,ar1+1,ar)就好了

#include <cstdio>#include <iostream>#include <algorithm>#define N 500010using namespace std;typedef pair<int,int> parii;int n;int a[N];parii b[N];struct func{  int mn,tot;  int val(int x){    return min(x+tot,mn);  }  friend func operator *(func a,func b){    a.tot+=b.tot;    a.mn=min(b.mn,a.mn+b.tot);    return a;  }};struct seg{  int l,r,mx;  func f;}T[N<<3];void Build(int g,int l,int r){  T[g].l=l; T[g].r=r; T[g].mx=-(1<<30);  T[g].f.tot=0; T[g].f.mn=1<<30;  if(l==r) return ;  int mid=l+r>>1;  Build(g<<1,l,mid); Build(g<<1|1,mid+1,r);  T[g].f=T[g<<1].f*T[g<<1|1].f;}void Update(int g,int x,int y){  T[g].mx=max(T[g].mx,y);  if(T[g].l==T[g].r){    T[g].f.tot++; T[g].f.mn=y;    return ;  }  int mid=T[g].l+T[g].r>>1;  if(x<=mid) Update(g<<1,x,y);  else Update(g<<1|1,x,y);  T[g].f=T[g<<1].f*T[g<<1|1].f;}int Calc(int g,int l,int r){  if(T[g].l==l&&T[g].r==r) return T[g].f.tot;  int mid=T[g].l+T[g].r>>1;  if(r<=mid) return Calc(g<<1,l,r);  if(l>mid) return Calc(g<<1|1,l,r);  return Calc(g<<1,l,mid)+Calc(g<<1|1,mid+1,r);}int Find(int g,int l,int r){  if(T[g].l==l&&T[g].r==r) return T[g].mx;  int mid=T[g].l+T[g].r>>1;  if(r<=mid) return Find(g<<1,l,r);  if(l>mid) return Find(g<<1|1,l,r);  return max(Find(g<<1,l,mid),Find(g<<1|1,mid+1,r));}func Query(int g,int l,int r){  if(T[g].l==l&&T[g].r==r) return T[g].f;  int mid=T[g].l+T[g].r>>1;  if(r<=mid) return Query(g<<1,l,r);  if(l>mid) return Query(g<<1|1,l,r);  return Query(g<<1,l,mid)*Query(g<<1|1,mid+1,r);}inline bool check(int x){  int num=Calc(1,1,x),last=Find(1,1,x);  return last<=-num;}int main(){  freopen("1.in","r",stdin);  freopen("1.out","w",stdout);  scanf("%d",&n);  for(int i=1;i<=n;i++)    scanf("%d",&a[i]),b[i]=parii(a[i],i);  sort(b+1,b+1+n);  for(int i=1;i<=n;i++) a[b[i].second]=i;  Build(1,1,n);  for(int i=1;i<=n;i++){    Update(1,a[i],b[a[i]].first);    int L=1,R=n,mid,cur=-1;    while(L<=R) check(mid=L+R>>1)?L=(cur=mid)+1:R=mid-1;    if(cur==-1) printf("%d\n",Query(1,1,n).val(0));    else{      int num=Calc(1,1,cur);      if(cur==n){ printf("%d\n",-num); continue; }      printf("%d\n",Query(1,cur+1,n).val(-num));    }  }  return 0;}
原创粉丝点击