zoukankan      html  css  js  c++  java
  • BZOJ 1901 Dynamic Rankings

    【题意】
    公司动态排名开发了一种新型计算机,不再满足于简单地找到给定N个数的第k个最小数。他们开发了一个更强大的系统,对于N个数a[1],a[2],…,a[N],你可以问它:a[i],a[i+1],…,a[j]的第k个最小数是多少?(i<=j,0<k<=j-i+1)。你甚至可以改变一些a[i]的值,并继续查询。
    你的任务是为这台计算机编写一个程序

    • 从输入中读取N个数字(1 <= N <= 50000)
    • 处理输入的M指令(1 <= M <= 10000)。这些指令包括查询a[i],a[i+1],…,a[j]的第k个最小数,或将a[i]改为t。
      【输入】
      输入的第一行是单个数字X(0<X<=4),即输入的测试用例的数量。然后每个X块代表一个测试用例。
      每个块的第一行包含两个整数N和M,表示N个数和M个指令。接下来是N行。第i+1行代表数字a[i]。然后是M行,格式如下
      Q i j k
      或者
      C i t
      它表示查询a[i],a[i+1],…,a[j]的第k个数,并分别将a[i]变为t。保证在任何操作时间,任何数字a[i]是小于1000000000的非负整数。
      两个连续测试用例之间没有空行。
      【输出】
      对于每个查询操作,输出一个整数来表示结果。(即a[i],a[i+1],…,a[j]的第k个最小数)
      两个连续测试用例之间没有空行。
      【输入样例】
      2
      5 3
      3 2 1 4 7
      Q 1 4 3
      C 2 6
      Q 2 5 3
      5 3
      3 2 1 4 7
      Q 1 4 3
      C 2 6
      Q 2 5 3

    【输出样例】
    3
    6
    3
    6

    整体分治模板题

    #include<cstdio>
    #include<cctype>
    #include<cstring>
    #include<algorithm>
    #define g getchar()
    using namespace std;
    const int N=70010;
    
    void qr(int &x) {
    	char c=g;x=0;
    	while(!isdigit(c))c=g;
    	while(isdigit(c))x=x*10+c-'0',c=g;
    }
    void write(int x) {
    	if(x/10)write(x/10);
    	putchar(x%10+'0');
    }
    void pri(int x) { write(x); puts("");}
    
    struct rec { int op,x,y,z;}q[N],lq[N],rq[N];//操作序列(按时间排列) 
    int T,t,p,n,m,a[N],b[N],tot,c[N],ans[N];
    //数据总数,操作数,询问数。 
    int ask(int x) {
    	int y=0;
    	for(	;x;x&=x-1) y+=c[x];
    	return y;
    }
    
    int up(int x,int y) {
    	for(	;x<=n;x+=x&-x) 
    		c[x]+=y;
    }
    
    void clear(int x) {
    	for(	;x&&c[x];x+=x&-x)
    		c[x]=0;
    }
    
    int sta[N],top;
    //整体分治其实就是把原问题分成若干个相同的子问题。
    //当问题缩小到一定规模时,答案自然水落石出。 
    void solve(int l,int r,int st,int ed) {
    	if(st>ed) return ;
    	if(l==r) {
    		for(int i=st;i<=ed;i++)
    			ans[q[i].op]=b[l];
    		return ;
    	}
    	int mid=(l+r)>>1,val=b[mid],lt=0,rt=0;
    	for(int i=st;i<=ed;i++) {
    		if(!q[i].op) {
    			if(q[i].y<=val) up(q[i].x,q[i].z),lq[++lt]=q[i],sta[++top]=q[i].x;
    			else rq[++rt]=q[i];
    		}
    		else {
    			int cnt=ask(q[i].y)-ask(q[i].x-1);
    			if(q[i].z<=cnt) lq[++lt]=q[i];
    			else q[i].z-=cnt,rq[++rt]=q[i];
    		}
    	}
    	while(top) clear(sta[top--]);//还原树状数组 
    	for(int i=1;i<=lt;i++) q[st+i-1]=lq[i];
    	for(int i=1;i<=rt;i++) q[st+lt+i-1]=rq[i];
    	solve(l,mid,st,st+lt-1);
    	solve(mid+1,r,st+lt,ed);
    }
    
    int main() {
    	qr(T);
    	while(T--) {
    		qr(n);qr(m);t=p=0;
    		for(int i=1;i<=n;i++) {
    			qr(a[i]);
    			q[++t]=(rec){0,i,a[i],1};
    		}
    		memcpy(b,a,(n+1)<<2); tot=n;
    		for(int i=1;i<=m;i++) {
    			char s[5];scanf("%s",s);
    			int l,r,k;qr(l);qr(r);
    			if(s[0]=='C') {//本题核心思想:把修改拆成 减去原来的数 + 加上现在的数 两个部分 
    				q[++t]=(rec){0,l,a[l],-1};
    				q[++t]=(rec){0,l,a[l]=r,1};
    				b[++tot]=r;
    			}
    			else qr(k),q[++t]=(rec){++p,l,r,k};
    		}
    		sort(b+1,b+tot+1); top=1;
    		for(int i=2;i<=tot;i++)
    			if(b[i]!=b[top]) b[++top]=b[i];//答案一定在出现的数中 
    		tot=top; top=0;
    		solve(1,tot,1,t);
    		for(int i=1;i<=p;i++) pri(ans[i]);
    	}
    	return 0;
    }
    	
    
  • 相关阅读:
    dvwa-Brute Force
    i春秋 Crypto模块rsa wrtiteup
    栈-函数调用
    Ymodem协议详解
    JAVA 传输post传输长字符、数据编码解码 反序列化字符串
    jquery datatable 全选,反选 参考文档
    java中bimface 在线申请token。模型视角 模型批注处理
    C# Winform 子窗体提交后更新父窗体datagridview数据(事件和委托)
    JAVA 两个时间 相差的 小时,天数,分钟
    JAVA 使用注解lombok@Builder和@Data,primary not found default constructor
  • 原文地址:https://www.cnblogs.com/zsyzlzy/p/12373876.html
Copyright © 2011-2022 走看看