• 【YBTOJ】【Luogu P2617】Dynamic Rankings


    链接:

    洛谷

    题目大意:

    给定一个含有 (n) 个数的序列 (a_1,a_2, dots, a_n),需要支持两种操作:

    • Q l r k 表示查询下标在区间 ([l,r]) 中的第 (k) 小的数。
    • C x y 表示将 (a_x) 改为 (y)

    正文:

    和静态区间第 (k) 小的思路基本相同,详见 可持久化数据结构。而不同的是,因为变成动态的,原来的主席树维护的前缀和不能再这么维护了,考虑用树状数组维护那个前缀和:在跑权值线段树的时候分别开两个树状数组维护前缀和,分别表示 ([1,l-1]) 区间和与 ([1,r]) 区间和,显然通过这两个树状数组能得到 ([l,r]) 前缀和。

    其余操作和静态区间第 (k) 小就一样了,然而还有一点需要注意,这道题需要卡常,请注意你的常数问题。

    代码:

    const int N = 100010;
    
    inline ll read()
    {
        char c;ll f = 0, d = 1;
        while(c = getchar(), !isdigit(c)) if(c == '-') d=-1;f=(f<<3)+(f<<1)+c-48;
        while(c = getchar(), isdigit(c)) f=(f<<3)+(f<<1)+c-48;
        return d*f;
    }
    
    int n, m, nn;
    ll a[N], b[N << 1]; int root[N * 600];
    ll inp[N][3], t[2][N], cntl, cntr;
    struct SegandTree_arrar 
    {
    	int lt[N * 600], rt[N * 600], cnt;
    	ll sum[N * 600];
    	void change(int &x, int l, int r, int p, int val)
    	{
    		if (!x) x = ++cnt; sum[x] += val;
    		if (l == r) return;
    		int mid = (l + r) >> 1;
    		if(p <= mid) change(lt[x], l, mid, p, val);
    		else change (rt[x], mid + 1, r, p, val);
    	}
    	int query(int l, int r, int k)
    	{
    		if (l == r) return l;
    		ll ans = 0;int mid = (l + r) >> 1;
    		for (int i = 1; i <= cntl; i++) ans -= sum[lt[t[0][i]]];
    		for (int i = 1; i <= cntr; i++) ans += sum[lt[t[1][i]]]; 
    		
    		if (k <= ans)
    		{
    			for (int i = 1; i <= cntl; i++) t[0][i] = lt[t[0][i]];
    			for (int i = 1; i <= cntr; i++) t[1][i] = lt[t[1][i]];
    			return query(l, mid, k);
    		}
    		else
    		{
    			for (int i = 1; i <= cntl; i++) t[0][i] = rt[t[0][i]];
    			for (int i = 1; i <= cntr; i++) t[1][i] = rt[t[1][i]];
    			return query(mid + 1, r, k - ans);
    		}
    	 } 
    	
    }sgt;
    
    void add(int pos, int val)
    {
    	int p = lower_bound(b + 1, b + 1 + nn, a[pos]) - b;
    	for (; pos <= n; pos += pos & -pos)  
    		sgt.change(root[pos], 1, nn, p, val);
    }
    
    int main()
    {
    	n = read(), m = read();
    	for (int i = 1; i <= (nn=n); i++)
    		a[i] = read(), b[i] = a[i];
    	for (int i = 1; i <= m; i++)
    	{
    		char s[5];
    		scanf ("%s", s);
    		inp[i][0] = read(), inp[i][1] = read();
    		if (s[0] == 'Q') inp[i][2] = read();
    		else b[++nn] = inp[i][1];
    	}
    	sort(b + 1, b + 1 + nn);
    	nn = unique(b + 1, b + 1 + nn) - b - 1;
    	for (int i = 1; i <= n; i++) add(i, 1);
    	for (int i = 1; i <= m; i++)
    	{
    		if (inp[i][2]) 
    		{
    			cntl = cntr = 0;
    			int l = inp[i][0], r = inp[i][1];
    			for (int x = r; x; x -= x & -x) t[1][++cntr] = root[x];
    			for (int x = l - 1; x; x -= x & -x) t[0][++cntl] = root[x];
    			printf ("%lld
    ", b[sgt.query(1, nn, inp[i][2])]);
    		}else
    		{
    			add(inp[i][0], -1);
    			a[inp[i][0]] = inp[i][1];
    			add(inp[i][0], 1);
    		}
    	}
    	return 0;
    } 
    
  • 相关阅读:
    解决ORACLE存储过程锁定的问题
    #{propName,attr1=val1,attr2=val2}
    集成confluence与jira
    jira4.1.1安装
    Mac OS X 10.6下安装MySQL 5.1.45
    JIRA+MySQL配置
    xcode4.5 iOS6 cocos2dx 横屏解决方案
    gSoap
    Jira5.0.2安装及破解
    MFC中显示cocos2dx
  • 原文地址:https://www.cnblogs.com/GJY-JURUO/p/14419133.html
Copyright © 2020-2023  润新知