zoukankan      html  css  js  c++  java
  • Dynamic Rankings

    洛咕

    题意:给定n个数的序列,维护两种操作,一是修改(a[x]=y),二是查询([l,r])中第(k)小的数是多少.(n,m<=100000).

    分析:在整体二分例题的基础上,增加了一个单点修改的操作.我们可以把一个单点修改操作(a[x]=y)分解为"将序列第x个数减去a[x]"和"将序列第x个数增加y"两个操作,同理原始序列的赋值也可以看做一个"将序列第x个数增加y"的操作,然后把这些操作和所有"询问"操作丢到一起进行整体二分,就还是模板了.

    为了在分治的过程区分操作,我们将增加操作的(opt)标记为0,减去操作的(opt)标记为-1,其余的询问操作按照顺序(方便离线回答)标记为大于等于1的数.

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<map>
    #include<set>
    #define ll long long
    using namespace std;
    inline int read(){
        int x=0,o=1;char ch=getchar();
        while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
        if(ch=='-')o=-1,ch=getchar();
        while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
        return x*o;
    }
    const int inf=1e9;
    const int N=100005;
    int n,m,tot,tim,a[N],c[N],ans[N];
    struct query{int opt,x,y,z;}q[N<<2],ql[N<<2],qr[N<<2];
    inline int lowbit(int x){return x&-x;}
    inline void add(int x,int v){for(;x<=n;x+=lowbit(x))c[x]+=v;}
    inline int ask(int x){int cnt=0;for(;x;x-=lowbit(x))cnt+=c[x];return cnt;}
    inline void solve(int l,int r,int st,int ed){
    	if(st>ed)return;
    	if(l==r){
    		for(int i=st;i<=ed;++i)
    			if(q[i].opt>=1)ans[q[i].opt]=l;
    		return;
    	}
    	int mid=(l+r)>>1,lt=0,rt=0;
    	for(int i=st;i<=ed;++i){
    		if(q[i].opt==-1){
    			if(q[i].y<=mid)add(q[i].x,-1),ql[++lt]=q[i];
    			else qr[++rt]=q[i];
    		}
    		else if(!q[i].opt){
    			if(q[i].y<=mid)add(q[i].x,1),ql[++lt]=q[i];
    			else qr[++rt]=q[i];
    		}
    		else if(q[i].opt>=1){
    			int sum=ask(q[i].y)-ask(q[i].x-1);
    			if(sum>=q[i].z)ql[++lt]=q[i];
    			else q[i].z-=sum,qr[++rt]=q[i];
    		}
    	}
    	for(int i=ed;i>=st;--i){
    		if(q[i].y>mid)continue;
    		if(q[i].opt==-1)add(q[i].x,1);
    		else if(!q[i].opt)add(q[i].x,-1);
    	}
    	for(int i=1;i<=lt;++i)q[st+i-1]=ql[i];
    	for(int i=1;i<=rt;++i)q[lt+st+i-1]=qr[i];
    	solve(l,mid,st,st+lt-1);solve(mid+1,r,st+lt,ed);
    }
    int main(){
    	n=read();m=read();
    	for(int i=1;i<=n;++i){
    		a[i]=read();
    		q[++tot].opt=0;q[tot].x=i;q[tot].y=a[i];
    	}
    	for(int i=1;i<=m;++i){
    		char ch;cin>>ch;
    		if(ch=='Q'){
    			q[++tot].opt=++tim;q[tot].x=read();q[tot].y=read();q[tot].z=read();
    		}
    		else if(ch=='C'){
    			int x=read(),y=read();
    			q[++tot].opt=-1;q[tot].x=x;q[tot].y=a[x];
    			a[x]=y;
    			q[++tot].opt=0;q[tot].x=x;q[tot].y=a[x];
    		}//一次单点修改分解为两个操作
    	}
    	solve(-inf,inf,1,tot);
    	for(int i=1;i<=tim;++i)printf("%d
    ",ans[i]);
        return 0;
    }
    
    
  • 相关阅读:
    单向链表
    字符串的碎片整理。。。
    刷夜有感
    C中的枚举类型及一些用法
    hdu 1001(无赖的一种方法)
    加法器和布尔运算符
    《C和指针》学习笔记(4)
    Java中创建对象的5种方式 -[转] http://www.codeceo.com/article/5-ways-java-create-object.html
    程序员转行为什么这么难--[转]
    Tomcat 性能优化之APR插件安装 -- [转]
  • 原文地址:https://www.cnblogs.com/PPXppx/p/11688126.html
Copyright © 2011-2022 走看看