zoukankan      html  css  js  c++  java
  • P1486 [NOI2004]郁闷的出纳员[权值线段树]

    权值线段树。

    我们只用维护一个人是否存在,以及他当前排名,而不关心工资的具体值,这个可以直接算。

    不难发现,如果不考虑新的员工,所有员工的工资的差值是不变的。

    而加进来一个新的员工时,其工资为(x),假设当前工资变化量为(delta),那么这个新员工与原来员工工资(x_i)的工资差就是(x-x_i-delta)

    根据这点,我们不难想到对所有员工仅维护(x_i-delta)这个东西,询问时加上当前的(delta)即可。

    即维护一颗权值线段树,维护(x_i-delta)出现的次数,并实时整体二分求第k大即可。

    注意一些小细节,(x_i-delta)有可能为负数,因此我们将维护的值域整体向右平移(N)

    话说这个题不加lazytag也能轻松跑过,数据真的弱。

    参考代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<string>
    #include<cstdlib>
    #include<queue>
    #include<vector>
    #define INF 0x3f3f3f3f
    #define PI acos(-1.0)
    #define N 401000
    #define M 200010
    #define MOD 2520
    #define E 1e-12
    using namespace std;
    inline int read()
    {
    	int f=1,x=0;char c=getchar();
    	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    	while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    	return x*f;
    }
    struct tree{
    	int l,r;
    	int sum,rem;
    }t[N<<2];
    int n,lim,delta,now,go;
    inline void pushdown(int p)
    {
    	if(t[p].rem){
    		t[p<<1].sum=t[p<<1|1].sum=0;
    		t[p<<1].rem=t[p<<1|1].rem=1;
    		t[p].rem=0;
    	}
    }
    inline void pushup(int p){t[p].sum=t[p<<1].sum+t[p<<1|1].sum;}
    inline void build(int p,int l,int r)
    {
    	t[p].l=l,t[p].r=r;
    	if(l==r){t[p].sum=0;return;}
    	int mid=(l+r)>>1;
    	build(p<<1,l,mid);
    	build(p<<1|1,mid+1,r);
    	pushup(p);
    } 
    inline void change(int p,int x,int val)
    {
    	if(t[p].l==t[p].r){
    		t[p].sum+=val;return;
    	}
    	pushdown(p);
    	int mid=(t[p].l+t[p].r)>>1;
    	if(x<=mid) change(p<<1,x,val);
    	else change(p<<1|1,x,val);
    	pushup(p);
    }
    inline int query(int p,int k)
    {
    	if(t[p].l==t[p].r) return t[p].l;
    	pushdown(p);
    	if(t[p<<1].sum>=k) return query(p<<1,k);
    	else return query(p<<1|1,k-t[p<<1].sum);
    }
    inline void upd(int p,int l,int r)
    {
    	if(l<=t[p].l&&t[p].r<=r){
    		if(t[p].sum) now-=t[p].sum,go+=t[p].sum;
    		t[p].sum=0,t[p].rem=1;return;
    	}
    	pushdown(p);
    	int mid=(t[p].l+t[p].r)>>1;
    	if(l<=mid) upd(p<<1,l,r);
    	if(r>mid) upd(p<<1|1,l,r);
    	pushup(p);
    }
    int main()
    {
    	n=read(),lim=read();
    	char op[2];
    	build(1,1,N);
    	for(int i=1;i<=n;++i){
    		scanf("%s",op);
    		int k=read();
    		if(op[0]=='I'){
    			if(k>=lim) change(1,k-delta+M,1),now++;
    		}
    		else if(op[0]=='A') delta+=k;
    		else if(op[0]=='S') delta-=k,upd(1,1,lim-delta-1+M);
    		else if(op[0]=='F'){
    			if(k>now) puts("-1");
    			else printf("%d
    ",query(1,now-k+1)+delta-M);
    		}
    	}
    	cout<<go<<endl;
    	return 0;
    }
    
  • 相关阅读:
    docker 安装nginx 并部署 配置本地化
    vue安装tinyMCE
    gitignore文件不生效的问题解决
    docker安装Mysql挂载数据卷 实现容器配置本地化
    淘宝网店经营场所证明如何下载
    leetcode 100.相同的树
    深度优先搜索和广度优先搜索
    leetcode 329 矩阵中的最长递增路径
    leetcode 410 分割数组的最大值
    leetcode 95 不同的二叉搜索树II
  • 原文地址:https://www.cnblogs.com/DarkValkyrie/p/11853513.html
Copyright © 2011-2022 走看看