zoukankan      html  css  js  c++  java
  • [bzoj1901][Zju2112]Dynamic Rankings【树套树】【树状数组】【线段树】

    【题目描述】

    Description

    给定一个含有n个数的序列a[1],a[2],a[3]……a[n],程序必须回答这样的询问:对于给定的i,j,k,在a[i],a[i+1
    ],a[i+2]……a[j]中第k小的数是多少(1≤k≤j-i+1),并且,你可以改变一些a[i]的值,改变后,程序还能针对改
    变后的a继续回答上面的问题。

    Input

    第一行有两个正整数n(1≤n≤10000),m(1≤m≤10000)。
    分别表示序列的长度和指令的个数。
    第二行有n个数,表示a[1],a[2]……a[n],这些数都小于10^9。
    接下来的m行描述每条指令
    每行的格式是下面两种格式中的一种。 
    Q i j k 或者 C i t 
    Q i j k (i,j,k是数字,1≤i≤j≤n, 1≤k≤j-i+1)
    表示询问指令,询问a[i],a[i+1]……a[j]中第k小的数。
    C i t (1≤i≤n,0≤t≤10^9)表示把a[i]改变成为t
    m,n≤10000

    Output

     对于每一次询问,你都需要输出他的答案,每一个输出占单独的一行。

    Sample Input

    5 3
    3 2 1 4 7
    Q 1 4 3
    C 2 6
    Q 2 5 3

    Sample Output

    3
    6

    HINT

    Source

    【题解】

     树状数组套权值线段树模板题。

     树状数组每一个节点下开一棵权值线段树,维护这个点所代表的区间。

    查询时,把树状数组上需要的节点全部提取出来,一起二分。

    修改时,把包含这个点的权值线段树都一起修改。

    复杂度 O(n log^2 n)

    /* --------------
        user Vanisher
        problem bzoj-1901 
    ----------------*/
    # include <bits/stdc++.h>
    # define 	ll 		long long
    # define 	N 		10010
    # define 	M 		5000000
    # define 	L 		0
    # define 	R 		1e9
    using namespace std;
    int read(){
    	int tmp=0, fh=1; char ch=getchar();
    	while (ch<'0'||ch>'9'){if (ch=='-') fh=-1; ch=getchar();}
    	while (ch>='0'&&ch<='9'){tmp=tmp*10+ch-'0'; ch=getchar();}
    	return tmp*fh;
    }
    struct node{
    	int num,pl,pr;
    }T[M];
    int h[N],a[N],place,incnum,inc[N],decnum,det[N],n,m;
    int lowbit(int x){
    	return x&(-x);
    }
    void extend(int p, int x, int l, int r){
    	T[p].num++;
    	if (l!=r){
    		int mid=(l+r)/2;
    		if (x<=mid){
    			if (T[p].pl==0) T[p].pl=++place;
    			extend(T[p].pl,x,l,mid);
    		}
    		else {
    			if (T[p].pr==0) T[p].pr=++place;
    			extend(T[p].pr,x,mid+1,r);
    		}
    	}
    }
    void del(int p, int x, int l, int r){
    	T[p].num--;
    	if (l!=r){
    		int mid=(l+r)/2;
    		if (x<=mid) del(T[p].pl,x,l,mid);
    			else del(T[p].pr,x,mid+1,r);
    	}
    }
    int build(int l, int r){
    	int p=++place;
    	for (int i=l; i<=r; i++)
    		extend(p,a[i],L,R);
    	return p;
    }
    void getinc(int x){
    	incnum=0;
    	while (x>0){
    		inc[++incnum]=h[x];
    		x=x-lowbit(x);
    	}
    }
    void getdec(int x){
    	decnum=0;
    	while (x>0){
    		det[++decnum]=h[x];
    		x=x-lowbit(x);
    	}
    }
    void modify(int p, int x, int k){
    	del(p,a[x],L,R);
    	extend(p,k,L,R);
    }
    int query(int num, int l, int r){
    	if (l==r) return l;
    	int mid=(l+r)/2,now=0;
    	for (int i=1; i<=incnum; i++) now=now+T[T[inc[i]].pl].num;
    	for (int i=1; i<=decnum; i++) now=now-T[T[det[i]].pl].num;
    	if (now>=num){
    		for (int i=1; i<=incnum; i++) inc[i]=T[inc[i]].pl;
    		for (int i=1; i<=decnum; i++) det[i]=T[det[i]].pl;
    		return query(num,l,mid);
    	}
    	else {
    		for (int i=1; i<=incnum; i++) inc[i]=T[inc[i]].pr;
    		for (int i=1; i<=decnum; i++) det[i]=T[det[i]].pr;
    		return query(num-now,mid+1,r);
    	}
    }
    int main(){
    	n=read(), m=read();
    	int l,r,k;
    	for (int i=1; i<=n; i++) a[i]=read();
    	for (int i=1; i<=n; i++){
    		l=i-lowbit(i)+1, r=i;
    		h[i]=build(l,r);
    	}
    	char opt;
    	for (int i=1; i<=m; i++){
    		scanf("
    %c",&opt);
    		if (opt=='Q'){
    			l=read(), r=read(); k=read();
    			getinc(r); 
    			getdec(l-1);
    			printf("%d
    ",query(k,L,R));
    		}
    		else {
    			l=read(), k=read(); r=l;
    			while (r<=n){
    				modify(h[r],l,k);
    				r=r+lowbit(r);
    			}
    			a[l]=k;
    		}
    	}
    	return 0;
    }


  • 相关阅读:
    Android OpenGL ES 2.0 (四) 灯光perfragment lighting
    Android OpenGL ES 2.0 (五) 添加材质
    冒泡排序函数
    javascript object 转换为 json格式 toJSONString
    Liunx CentOS 下载地址
    jquery 图片切换特效 鼠标点击左右按钮焦点图切换滚动
    javascript 解析csv 的function
    mysql Innodb Shutdown completed; log sequence number解决办法
    Centos 添加 yum
    javascript 键值转换
  • 原文地址:https://www.cnblogs.com/Vanisher/p/9136024.html
Copyright © 2011-2022 走看看