• [洛谷P2617] Dynamic Rankings


    前言

    整体二分永远滴神!

    树套树?*都不写。

    题目

    洛谷

    讲解

    把初始序列当成加入数字,修改当成删除+加入数字。

    二分的是答案,考虑二分出来一个值之后所有数字其实都变成了01,所以不用离散化,可以直接上小常数树状数组。

    好久没打整体二分都忘了询问放到右边要减去左边的贡献了= =

    代码

    超短代码~
    //12252024832524
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define TT template<typename T>
    using namespace std; 
    
    typedef long long LL;
    const int MAXN = 300005;
    int n,m,cnt,qtot;
    int a[MAXN],ans[MAXN];
    
    LL Read()
    {
    	LL x = 0,f = 1;char c = getchar();
    	while(c > '9' || c < '0'){if(c == '-')f = -1;c = getchar();}
    	while(c >= '0' && c <= '9'){x = (x*10) + (c^48);c = getchar();}
    	return x * f;
    }
    TT void Put1(T x)
    {
    	if(x > 9) Put1(x/10);
    	putchar(x%10^48);
    }
    TT void Put(T x,char c = -1)
    {
    	if(x < 0) putchar('-'),x = -x;
    	Put1(x); if(c >= 0) putchar(c);
    }
    TT T Max(T x,T y){return x > y ? x : y;}
    TT T Min(T x,T y){return x < y ? x : y;}
    TT T Abs(T x){return x < 0 ? -x : x;}
    
    struct node
    {
    	int opt,l,r,k,ID;
    	//  opt pos f val 0
    }t[MAXN],tl[MAXN],tr[MAXN];
    int b[MAXN];
    int lowbit(int x){return x & -x;}
    void Add(int x,int val){for(int i = x;i <= n;i += lowbit(i)) b[i] += val;}
    int Sum(int x){int ret = 0;for(int i = x;i >= 1;i -= lowbit(i)) ret += b[i];return ret;}
    void solve(int l,int r,int x,int y)
    {
    	if(l == r){for(int i = x;i <= y;++ i) if(t[i].ID) ans[t[i].ID] = l;return;}
    	int mid = (l+r) >> 1,cl = 0,cr = 0,ql = 0,qr = 0;
    	for(int i = x;i <= y;++ i)
    	{
    		if(!t[i].opt)
    		{
    			if(t[i].k <= mid) Add(t[i].l,t[i].r),tl[++cl] = t[i];
    			else tr[++cr] = t[i];
    		}
    		else
    		{
    			int c = Sum(t[i].r) - Sum(t[i].l-1);
    			if(c >= t[i].k) tl[++cl] = t[i],ql = 1;
    			else tr[++cr] = t[i],tr[cr].k -= c,qr = 1;
    		}
    	}
    	for(int i = x;i <= y;++ i) if(!t[i].opt && t[i].k <= mid) Add(t[i].l,-t[i].r);
    	for(int i = 1;i <= cl;++ i) t[x+i-1] = tl[i];
    	for(int i = 1;i <= cr;++ i) t[x+cl+i-1] = tr[i];
    	if(ql) solve(l,mid,x,x+cl-1);
    	if(qr) solve(mid+1,r,x+cl,y);
    }
    
    int main()
    {
    //	freopen(".in","r",stdin);
    //	freopen(".out","w",stdout);
    	n = Read(); m = Read();
    	for(int i = 1;i <= n;++ i) a[i] = Read(),t[++cnt] = {0,i,1,a[i],0};
    	for(int i = 1;i <= m;++ i)
    	{
    		char c = getchar(); while(c != 'Q' && c != 'C') c = getchar();
    		int x = Read(),y = Read();
    		if(c == 'Q') t[++cnt] = {1,x,y,Read(),++qtot};
    		else t[++cnt] = {0,x,-1,a[x],0},t[++cnt] = {0,x,1,a[x]=y,0};
    	}
    	solve(0,1e9,1,cnt);
    	for(int i = 1;i <= qtot;++ i) Put(ans[i],'
    ');
    	return 0;
    }
    
  • 相关阅读:
    10. 正则表达式匹配
    svn 类似.gitignore功能实现
    GF学习未解之谜
    cocos
    unity 编辑器内对Game视图进行截图
    Roughlike游戏里面的随机数种子
    网站推荐——游戏图标网
    Unity 使用image绘制线段 直线
    c# unity 异步任务队列
    Unity编辑器调用外部exe程序 和 windows文件夹
  • 原文地址:https://www.cnblogs.com/PPLPPL/p/15251791.html
Copyright © 2020-2023  润新知