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

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

POJ2104的拓展.

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

具体实现可以看代码.

时间复杂度O((n+m)loga[i]logn)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;
}
发布了225 篇原创文章 · 获赞 66 · 访问量 7万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 深蓝海洋 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览