zoukankan      html  css  js  c++  java
  • 【刷题】BZOJ 1901 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

    Solution

    这是一道树套树的题目,树状数组套主席树
    从最基本的开始
    找区间第(k)大,主席树
    如果我们对于修改直接暴力做,那么正确性保证,但复杂度不能承受
    那么我们就想什么东西可以帮助主席树维护动态的前缀和(静态的查询其实主席树自己就把前缀和做了),而查询第(k)大的事情还是由主席树做
    于是我们就想到了BIT(树状数组)
    常用的BIT可以支持单点修改求前缀和
    那么我们把BIT的“点”变成主席树的“树”,就可以完成这道题了

    #include<bits/stdc++.h>
    #define ll long long
    #define db double
    #define ld long double
    #define Mid ((l+r)>>1)
    #define lson l,Mid
    #define rson Mid+1,r
    #define left 0
    #define right 1
    const int MAXN=10000+10;
    int n,m,A[MAXN];
    struct node{
    	char opt;
    	int i,j,k,t;
    };
    node Q[MAXN];
    std::vector<int> V;
    std::map<int,int> M;
    struct ChairManTree_BIT{
    	int cnt,lc[MAXN<<9],rc[MAXN<<9],num[MAXN<<9],root[MAXN],need[2][20],nt[2],size;
    	inline void init()
    	{
    		cnt=0;
    		memset(lc,0,sizeof(lc));
    		memset(rc,0,sizeof(rc));
    		memset(num,0,sizeof(num));
    	}
    	inline int lowbit(int x)
    	{
    		return x&(-x);
    	}
    	inline void Insert(int &rt,int l,int r,int pos,int val)
    	{
    		if(!rt)rt=++cnt;
    		num[rt]+=val;
    		if(l==r)return ;
    		else
    		{
    			if(pos<=Mid)Insert(lc[rt],lson,pos,val);
    			else Insert(rc[rt],rson,pos,val);
    		}
    	}
    	inline void add(int x,int k,int p)
    	{
    		while(x<=n)
    		{
    			Insert(root[x],1,size,k,p);
    			x+=lowbit(x);
    		}
    	}
    	inline void Gneed(int nxt[])
    	{
    		for(register int i=1;i<=nt[left];++i)need[left][i]=nxt[need[left][i]];
    		for(register int i=1;i<=nt[right];++i)need[right][i]=nxt[need[right][i]];
    	}
    	inline int Query(int l,int r,int k)
    	{
    		if(l==r)return l;
    		else
    		{
    			int t=0;
    			for(register int i=1;i<=nt[right];++i)t+=num[lc[need[right][i]]];
    			for(register int i=1;i<=nt[left];++i)t-=num[lc[need[left][i]]];
    			if(k<=t)
    			{
    				Gneed(lc);
    				return Query(lson,k);
    			}
    			else
    			{
    				Gneed(rc);
    				return Query(rson,k-t);
    			}
    		}
    	}
    	inline int sum(int l,int r,int k)
    	{
    		nt[left]=nt[right]=0;
    		l--;
    		while(l>0)
    		{
    			need[left][++nt[left]]=root[l];
    			l-=lowbit(l);
    		}
    		while(r>0)
    		{
    			need[right][++nt[right]]=root[r];
    			r-=lowbit(r);
    		}
    		return Query(1,size,k);
    	}
    };
    ChairManTree_BIT T;
    template<typename T> inline void read(T &x)
    {
    	T data=0,w=1;
    	char ch=0;
    	while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    	if(ch=='-')w=-1,ch=getchar();
    	while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar();
    	x=data*w;
    }
    template<typename T> inline void write(T x,char c='')
    {
    	if(x<0)putchar('-'),x=-x;
    	if(x>9)write(x/10);
    	putchar(x%10+'0');
    	if(c!='')putchar(c);
    }
    template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);}
    template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);}
    template<typename T> inline T min(T x,T y){return x<y?x:y;}
    template<typename T> inline T max(T x,T y){return x>y?x:y;}
    inline void newnum(int &x)
    {
    	int pre=x;
    	x=lower_bound(V.begin(),V.end(),x)-V.begin()+1;
    	M[x]=pre;
    }
    inline void discre()
    {
    	std::sort(V.begin(),V.end());
    	V.erase(unique(V.begin(),V.end()),V.end());
    	T.size=V.size();
    	for(register int i=1;i<=n;++i)newnum(A[i]);
    	for(register int i=1;i<=m;++i)
    		if(Q[i].opt=='C')newnum(Q[i].t);
    }
    int main()
    {
    	read(n);read(m);
    	for(register int i=1;i<=n;++i)
    	{
    		read(A[i]);
    		V.push_back(A[i]);
    	}
    	for(register int i=1;i<=m;++i)
    	{
    		std::cin>>Q[i].opt;
    		if(Q[i].opt=='Q')read(Q[i].i),read(Q[i].j),read(Q[i].k);
    		else
    		{
    			read(Q[i].i),read(Q[i].t);
    			V.push_back(Q[i].t);
    		}
    	}
    	discre();
    	T.init();
    	for(register int i=1;i<=n;++i)T.add(i,A[i],1);
    	for(register int i=1;i<=m;++i)
    	{
    		if(Q[i].opt=='Q')write(M[T.sum(Q[i].i,Q[i].j,Q[i].k)],'
    ');
    		if(Q[i].opt=='C')
    		{
    			T.add(Q[i].i,A[Q[i].i],-1);
    			A[Q[i].i]=Q[i].t;
    			T.add(Q[i].i,A[Q[i].i],1);
    		}
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    Visual Studio 2010 C++ 属性设置基础
    Visual Studio 2010 C++ 工程文件解读
    编译Python2.7.10
    编译libmemcached
    python2.7.10 VS2015编译方法
    zlib编译方法
    Openssl VS编译方法
    STL容器
    C++数值类型与string的相互转换
    NGINX配置文件详解
  • 原文地址:https://www.cnblogs.com/hongyj/p/8624340.html
Copyright © 2011-2022 走看看