• Dynamic Rankings


    II.Dynamic Rankings

    树状数组套权值线段树。

    正经不带修的方法就是主席树(即一堆权值线段树并一起)。现在带修了,那就把这些主席树拆开,拆成\(n\)棵权值线段树,然后用树状数组进行单点修改以及前缀求和,复杂度\(O(n\log^2n)\)

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define mid ((l+r)>>1)
    int n,m,root[100100],cnt,bin[1001000],tp,lim,num[100100];
    vector<int>v;
    struct node{
    	int lson,rson,sum;
    }seg[20001000];
    int newid(){
    	if(!tp)return ++cnt;
    	return bin[tp--];
    }
    void ADD(int &x,int l,int r,int P,int val){
    	if(l>P||r<P)return;
    	if(!x)x=newid();
    	seg[x].sum+=val;
    	if(l==r)return;
    	ADD(seg[x].lson,l,mid,P,val),ADD(seg[x].rson,mid+1,r,P,val);
    	if(!seg[x].sum)bin[++tp]=x,x=0;
    }
    void add(int x,int y,int z){
    	while(x<=n)ADD(root[x],1,lim,y,z),x+=x&-x;
    }
    int Query(vector<int>&x,vector<int>&y,int l,int r,int k){
    	if(l==r)return l;
    	int lsum=0;
    	for(auto i:x)lsum+=seg[seg[i].lson].sum;
    	for(auto i:y)lsum-=seg[seg[i].lson].sum;
    	if(k<=lsum){
    		for(auto &i:x)i=seg[i].lson;
    		for(auto &i:y)i=seg[i].lson;
    		return Query(x,y,l,mid,k);
    	}else{
    		for(auto &i:x)i=seg[i].rson;
    		for(auto &i:y)i=seg[i].rson;
    		return Query(x,y,mid+1,r,k-lsum);
    	}
    }
    int ask(int l,int r,int k){
    	vector<int>x,y;
    	l--;
    	while(r)x.push_back(root[r]),r-=r&-r;
    	while(l)y.push_back(root[l]),l-=l&-l;
    	return Query(x,y,1,lim,k);
    }
    struct opt{
    	int op,x,y,z;
    }q[100100];
    void iterate(int x,int l,int r){
    	if(!x)return;
    	iterate(seg[x].lson,l,mid),iterate(seg[x].rson,mid+1,r);
    }
    int main(){
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;i++)scanf("%d",&num[i]),v.push_back(num[i]);
    	for(int i=1;i<=m;i++){
    		char s[10];
    		scanf("%s",s);
    		if(s[0]=='Q')q[i].op=1,scanf("%d%d%d",&q[i].x,&q[i].y,&q[i].z);
    		else q[i].op=2,scanf("%d%d",&q[i].x,&q[i].y),v.push_back(q[i].y);
    	}
    	sort(v.begin(),v.end()),v.resize(unique(v.begin(),v.end())-v.begin()),lim=v.size();
    //	for(auto i:v)printf("%d ",i);puts("");
    	for(int i=1;i<=n;i++)add(i,num[i]=lower_bound(v.begin(),v.end(),num[i])-v.begin()+1,1);
    	for(int i=1;i<=m;i++){
    		if(q[i].op==1)printf("%d\n",v[ask(q[i].x,q[i].y,q[i].z)-1]);
    		else add(q[i].x,num[q[i].x],-1),add(q[i].x,num[q[i].x]=lower_bound(v.begin(),v.end(),q[i].y)-v.begin()+1,1);
    	}
    	return 0;
    }
    

  • 相关阅读:
    巧用$.extend
    easyui 表格中combo选择值后显示为valueField而非textField的解决
    jeasyui 造成$.data(...) is undefined报错的原因及解决
    无线路由器+摩托罗拉手机WIFI=能连接,但不能上网
    javascript 复制粘贴功能 各种浏览器兼容
    WriteLiteral与Write的区别
    打印机队列取消不了的解决方法
    js判断字符串长度,中文占两个字符
    针对chrome的css hack
    JS生成26个英文字母
  • 原文地址:https://www.cnblogs.com/Troverld/p/14611066.html
Copyright © 2020-2023  润新知