EC Round 41 (Rated for Div. 2)主席树 E. Tufurama

  简单分析一下,对于x<y,求a[x]>=y 同时a[y]>=x

  再简化一下,求1-a[y]区间内大于>=y的个数。。。主席树牛逼

  

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<vector>
#define LL long long
using namespace std;
const int maxx = 2e5+6;
struct node{
  int l,r;
  int cnt;
}tree[maxx*40];
int a[maxx];
int b[maxx];
int root[maxx];
int cnt;
vector<int>v;
int getval(int x){
    return lower_bound(v.begin(),v.end(),x)-v.begin()+1;
}
void inserts(int l,int r,int pre,int &now,int pos){
   now=++cnt;
   tree[now]=tree[pre];
   tree[now].cnt++;
   if(l==r){
    return ;
   }
   int mid=(l+r)>>1;
   if (pos<=mid){
    inserts(l,mid,tree[pre].l,tree[now].l,pos);
   }else {
    inserts(mid+1,r,tree[pre].r,tree[now].r,pos);
   }
}
int query(int L,int R,int l,int r,int w){
    if(l==r){
        return tree[R].cnt-tree[L].cnt;
    }
    int mid=(l+r)>>1;
    if(w<=mid){
       return tree[tree[R].r].cnt-tree[tree[L].r].cnt+query(tree[L].l,tree[R].l,l,mid,w);
    }else {
       return query(tree[L].r,tree[R].r,mid+1,r,w);
    }
}
int main(){
  int n;
  while(~scanf("%d",&n)){
      for (int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        v.push_back(a[i]);
      }
      sort(v.begin(),v.end());
      v.erase(unique(v.begin(),v.end()),v.end());
      for(int i=1;i<=n;i++){
        b[i]=getval(a[i]);
      }
      for (int i=1;i<=n;i++){
         inserts(1,n,root[i-1],root[i],b[i]);
      }
      LL ans=0;
      for (int i=2;i<=n;i++){
          ans+=query(root[0],root[min(a[i],i-1)],1,n,getval(i));
      }
      printf("%lld\n",ans);
  }
  return 0;
}

猜你喜欢

转载自www.cnblogs.com/bluefly-hrbust/p/11420991.html