BZOJ1901 Dynamic Rankings 题解(离线分治+树状数组)

版权声明:转载请注明原出处啦QAQ(虽然应该也没人转载): https://blog.csdn.net/hzk_cpp/article/details/90319217

题目:BZOJ1901.
题目大意:给定一个长度为 n n 的序列 a a ,支持 m m 次操作:
1.格式 Q   i   j   k Q\,i\,j\,k ,表示查询区间 [ i , j ] [i,j] 中第 k k 大的数.
2.格式 C   i   t C\,i\,t ,表示把 a [ i ] a[i] 改成 t t .
1 n , m 1 0 4 , 0 a [ i ] , t 1 0 9 1\leq n,m\leq 10^4,0\leq a[i],t\leq 10^9 .

POJ2104的拓展.

由于现在有了真正的修改操作,所以考虑把修改拆成两个,一个是把原来这个位置上的数的贡献撤销,一个是给这个位置上加入新数的贡献.

具体实现可以看代码.

时间复杂度 O ( ( n + m ) log a [ i ] log n ) O((n+m)\log a[i]\log n) .

代码如下:

#include<bits/stdc++.h>
  using namespace std;

#define Abigail inline void
typedef long long LL;

const int N=10000,INF=1000000000;

char rc(){
  char c=getchar();
  for (;c<'A'||c>'Z';c=getchar());
  return c;
}

int n,m,c[N+9],a[N+9];

void Add(int p,int v){if (!p) return;for (;p<=n;p+=p&-p) c[p]+=v;}
int Query(int p){int res=0;for (;p;p-=p&-p) res+=c[p];return res;}
int Query(int l,int r){return Query(r)-Query(l-1);}

struct question{
  int opt,x,y,z,id;
  question(int Opt=0,int X=0,int Y=0,int Z=0,int Id=0){opt=Opt;x=X;y=Y;z=Z;id=Id;}
}q[N*3+9],lq[N*3+9],rq[N*3+9];
int cq,ans[N+9];

void Divide(question *q,int L,int R,int h,int t){
  if (h>t) return;
  if (L==R){
  	for (int i=h;i<=t;++i)
  	  if (!q[i].opt) ans[q[i].id]=L;
  	return;
  }
  int mid=L+R>>1,lt=0,rt=0,tmp;
  for (int i=h;i<=t;++i)
    if (q[i].opt){
	  if (q[i].y>mid) rq[++rt]=q[i];
	  else Add(q[i].x,q[i].z),lq[++lt]=q[i];
	}else{
	  tmp=Query(q[i].x,q[i].y);
	  if (q[i].z<=tmp) lq[++lt]=q[i];
	  else q[i].z-=tmp,rq[++rt]=q[i];
	}
  for (int i=h;i<=t;++i)
    if (q[i].opt&&q[i].y<=mid) Add(q[i].x,-q[i].z);
  for (int i=1;i<=lt;++i) q[h+i-1]=lq[i];
  for (int i=1;i<=rt;++i) q[h+lt+i-1]=rq[i];
  Divide(q,L,mid,h,h+lt-1);
  Divide(q,mid+1,R,h+lt,t);
}

Abigail into(){
  scanf("%d%d",&n,&m);
  for (int i=1;i<=n;++i){
    scanf("%d",&a[i]);
    q[++cq]=question(1,i,a[i],1,0);
  }
  char opt;
  int x,y,z;
  for (int i=1;i<=m;++i){
    opt=rc();
	if (opt=='C'){
	  scanf("%d%d",&x,&y);
	  q[++cq]=question(1,x,a[x],-1,0);
	  q[++cq]=question(1,x,y,1,0);
	  a[x]=y;
	}else{
	  scanf("%d%d%d",&x,&y,&z);
	  q[++cq]=question(0,x,y,z,i);
	}
	ans[i]=-1;
  }
}

Abigail work(){
  Divide(q,0,INF,1,cq);
}

Abigail outo(){
  for (int i=1;i<=m;++i)
    if (ans[i]^-1) printf("%d\n",ans[i]);
}

int main(){
  into();
  work();
  outo();
  return 0;
}

猜你喜欢

转载自blog.csdn.net/hzk_cpp/article/details/90319217