zoukankan      html  css  js  c++  java
  • 【bzoj1901】Zju2112 Dynamic Rankings

    题目描述:

    给定一个含有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继续回答上面的问题。你需要编一个这样的程序,从输入文件中读入序列a,然后读入一系列的指令,包括询问指令和修改指令。对于每一个询问指令,你必须输出正确的回答。 第一行有两个正整数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。

    样例输入:

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


    样例输出:

    3
    6


    题解:
    序列上的带修改的求区间第k小。树状数组套可持久化线段树。其实主席树的每一次Insert相当于一次线性变化(大雾),然后普通的主席树是按照上一个版本进行的变化,如果要修改的话那就用树状数组来维护这个线性变化,使得修改的复杂度从O(nlogn)降到了O((logn)^2)。


    代码:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    
    #ifdef WIN32
    	#define LL "%I64d"
    #else
    	#define LL "%lld"
    #endif
    
    #ifdef CT
    	#define debug(...) printf(__VA_ARGS__)
    	#define setfile() 
    #else
    	#define debug(...)
    	#define filename ""
    	#define setfile() freopen(filename".in","r",stdin);freopen(filename".out","w",stdout);
    #endif
    
    #define R register
    #define getc() (S==T&&(T=(S=B)+fread(B,1,1<<15,stdin),S==T)?EOF:*S++)
    #define dmax(_a, _b) ((_a) > (_b) ? (_a) : (_b))
    #define dmin(_a, _b) ((_a) < (_b) ? (_a) : (_b))
    #define cmax(_a, _b) (_a < (_b) ? _a = (_b) : 0)
    #define cmin(_a, _b) (_a > (_b) ? _a = (_b) : 0)
    char B[1<<15],*S=B,*T=B;
    inline int FastIn()
    {
    	R char ch;R int cnt=0;R bool minus=0;
    	while (ch=getc(),(ch < '0' || ch > '9') && ch != '-');
    	ch == '-' ?minus=1:cnt=ch-'0';
    	while (ch=getc(),ch >= '0' && ch <= '9') cnt = cnt * 10 + ch - '0';
    	return minus?-cnt:cnt;
    }
    #define maxt 6200010
    #define maxn 10010
    const int oo = 1e9;
    int root[maxn], sum[maxt], ls[maxt], rs[maxt], tot, lcnt, rcnt, val[maxn], lr[maxn], rr[maxn];
    #define lowbit(_x) ((_x) & -(_x))
    int update (R int last, R int l, R int r, R int pre,R int c)
    {
    	R int mid = l + r >> 1, nw = ++tot;
    	sum[nw] = sum[last] + c;
    	if (l == r) return nw;
    	if (pre > mid)
    	{
    		ls[nw] = ls[last];
    		rs[nw] = update(rs[last], mid + 1, r, pre, c);
    	}
    	else
    	{
    		rs[nw] = rs[last];
    		ls[nw] = update(ls[last], l, mid, pre, c);
    	}
    	return nw;
    }
    inline int query(R int l, R int r, R int k)
    {
    	while (l < r)
    	{
    		R int lsum = 0, rsum = 0, mid = l + r >> 1;
    		for (R int i = 1; i <= lcnt; ++i)
    			lsum += sum[ls[lr[i]]];
    		for (R int i = 1; i <= rcnt; ++i)
    			rsum += sum[ls[rr[i]]];
    		if (rsum - lsum >= k)
    		{
    			for (R int i = 1; i <= lcnt; ++i)
    				lr[i] = ls[lr[i]];
    			for (R int i = 1; i <= rcnt; ++i)
    				rr[i] = ls[rr[i]];
    			r = mid;
    		}
    		else
    		{
    			for (R int i = 1; i <= lcnt; ++i)
    				lr[i] = rs[lr[i]];
    			for (R int i = 1; i <= rcnt; ++i)
    				rr[i] = rs[rr[i]];
    			l = mid + 1;
    			k -= (rsum - lsum);
    		}
    	}
    	return l;
    }
    int main()
    {
    //	setfile();
    	R int n = FastIn(), q = FastIn();
    	for (R int i = 1; i <= n; ++i)
    	{
    		R int a = FastIn();
    		for (R int j = i; j <= n; j += lowbit(j))
    			root[j] = update(root[j], 0, oo, a, 1);
    		val[i] = a;
    	}
    	for (R int i = 1; i <= q; ++i)
    	{
    		R char cmd = getc();
    		while (cmd!='Q'&&cmd!='C') cmd = getc();
    		R int a = FastIn(), b = FastIn();
    		if (cmd == 'Q')
    		{
    			R int k = FastIn();
    			lcnt  = rcnt = 0;
    			for (R int j = a - 1; j; j -= lowbit(j))
    				lr[++lcnt] = root[j];
    			for (R int j = b; j; j -= lowbit(j))
    				rr[++rcnt] = root[j];
    			printf("%d
    ",query(0, oo, k) );
    		}
    		else
    		{
    			for (R int j = a; j <= n; j += lowbit(j))
    				root[j] = update(root[j], 0, oo, val[a], -1);
    			val[a] = b;
    			for (R int j = a; j <= n; j += lowbit(j))
    				root[j] = update(root[j], 0, oo, b, 1);
    		}
    	}
    	return 0;
    }
    



  • 相关阅读:
    原生js ajax与jquery ajax的区别
    ajax的五大步骤
    js中setTimeout()时间参数设置为0的探讨
    js数组与字符串的相互转换方法
    javascript的三个组成部分
    linq 获取不重复数据,重复数据 var unique = arr.GroupBy(o => o).Where(g => g.Count() == 1) .Select(g => g.ElementAt(0));
    C# 随机 抽奖 50个随机码 不重复
    聚集索引和非聚集索引 聚集索引的叶节点就是最终的数据节点,而非聚集索引的叶节仍然是索引节点,但它有一个指向最终数据的指针。
    WPF ControlTemplate,DataTemplate
    C# 实现 奇数偶数排序,奇数在前,偶数在后
  • 原文地址:https://www.cnblogs.com/cocottt/p/6765024.html
Copyright © 2011-2022 走看看