C46【模板】权值线段树+离散化 P1908 逆序对

视频链接:C46【模板】权值线段树+离散化 P1908 逆序对_哔哩哔哩_bilibili

 

 

 

Luogu P1908 逆序对

//权值线段树+离散化 nlogn
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

#define ls u<<1
#define rs u<<1|1
#define mid ((l+r)>>1)
#define LL long long
const int N=500005;
int n,m,a[N],b[N];
int sum[N<<2]; //区间数的出现次数之和

void pushup(int u){ //上传
  sum[u]=sum[ls]+sum[rs];
}
void change(int u,int l,int r,int x){ //点修
  if(l==r){sum[u]++; return;}
  if(x<=mid) change(ls,l,mid,x);
  else change(rs,mid+1,r,x);
  pushup(u);
}
LL query(int u,int l,int r,int x,int y){ //区查
  if(x<=l && r<=y) return sum[u];
  LL s=0;
  if(x<=mid) s+=query(ls,l,mid,x,y);
  if(y>mid) s+=query(rs,mid+1,r,x,y);
  return s;
}
int main(){
  scanf("%d",&n);
  for(int i=1; i<=n; i++) 
    scanf("%d",&a[i]),b[i]=a[i];
  sort(b+1,b+n+1);
  LL s=0;
  for(int i=1; i<=n; i++){
    int id=lower_bound(b+1,b+n+1,a[i])-b;
    change(1,1,n,id);
    s+=query(1,1,n,id+1,n);
    //id右面的数是先插入且大于id的数
  }
  printf("%lld\n",s);
}

 

Luogu P3988 [SHOI2013] 发牌

// 权值线段树
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

void read(int &x){ //快读
  x=0; char c=getchar();
  while(!isdigit(c))c=getchar();
  while(isdigit(c))x=x*10+c-'0',c=getchar();
}
#define ls u<<1
#define rs u<<1|1
#define mid ((l+r)>>1)
int n,sum[3000005];

void build(int u,int l,int r){
  if(l==r){sum[u]=1; return;}
  build(ls,l,mid);
  build(rs,mid+1,r);
  sum[u]=sum[ls]+sum[rs];
}
int query(int u,int l,int r,int k){
  sum[u]--;
  if(l==r) return l;
  if(k<=sum[ls]) return query(ls,l,mid,k);
  else return query(rs,mid+1,r,k-sum[ls]);
}
int main(){
  read(n);
  build(1,1,n);
  int x,y=0;
  for(int i=n; i>=1; --i){
    read(x); y=(y+x)%i;
    printf("%d\n",query(1,1,n,y+1));
  }
}

 

posted @ 2023-10-20 21:00  董晓  阅读(302)  评论(0编辑  收藏  举报