• GMOJ 3571. 【GDKOI2014】内存分配 题解


    这题有一个显然不优的正解。

    思路

    对于一个进程 ({a_i,b_i}) ,其需要的额外的内存为 (b_i-sumlimits_{b_j<b_i}) ,也就是 (b_i-) 已经释放的内存和。

    那么对于所有的进程,需要的内存就为每一个进程需要内存的最大值,即 (max{left{b_i-sumlimits_{b_j<b_i} ight}})

    感性理解一下就是最大的“断层”。证明就算了

    这个式子可以用线段树维护,我们对于每一个进程,把 (b_i+1) 及以后减去 (a_i) ,每次修改把之前的贡献去掉再加上新的即可。

    一开始把所有的 (b_i) 先扔进去。

    如果用线段树做需要离散化,由于 (b_i) 排序后是单调递增的,所以不会影响正确性。同时,要注意维护所有 (b_i) 的最大值,最大值后的值不能查询(但还要正常修改,因为最大值可能变大),这个可以多记录一个 (cnt) 表示区间内是否有进程完成。当然,每次修改时也要把单个点的 (cnt) 修改掉。(所以显然很慢)

    当然,使用可以区间修改的平衡树也许可以完美避免上述问题。但我不知道怎么打

    Code

    由于不(lan)喜(de)欢(bei) STL离散化,以及需要跨数组离散化,这里使用指针离散化。

    #include<cstdio>
    #include<algorithm>
    #define mid ((l+r)>>1)
    using namespace std;
    struct tree{
    	long long mx,cnt,s;
    }t[600010];
    int n,m,mx=1,a[200010][2],c[200010][3],*l[200010],num[200010];
    template<typename T>void read(T &x){
    	char c=getchar();
    	for(;c<33;c=getchar());
    	for(x=0;47<c&&c<58;x=x*10+c-48,c=getchar());
    }
    bool comp(int *x,int *y){
    	return(*x<*y);
    }
    void pushdown(int m){
    	t[m<<1].s+=t[m].s;t[m<<1].mx+=t[m].s;
    	t[m<<1|1].s+=t[m].s;t[m<<1|1].mx+=t[m].s;
    	t[m].s=0;
    }
    void update(int m){
    	t[m].mx=max(t[m<<1].mx,t[m<<1|1].mx);
    	t[m].cnt=t[m<<1].cnt+t[m<<1|1].cnt;
    }
    void sg(int m,int x,int y,int c,int l,int r){     //区间修改
    	if(x<=l&&r<=y){
    		t[m].s+=c;
    		t[m].mx+=c;
    		return;
    	}
    	pushdown(m);
    	if(x<=mid){
    		sg(m<<1,x,y,c,l,mid);
    	}
    	if(y>mid){
    		sg(m<<1|1,x,y,c,mid+1,r);
    	}
    	update(m);
    }
    void point(int m,int x,int z,int l,int r){     //对cnt进行修改
    	if(l==r){
    		t[m].cnt+=z;
    		return;
    	}
    	pushdown(m);
    	if(x<=mid){
    		point(m<<1,x,z,l,mid);
    	}else{
    		point(m<<1|1,x,z,mid+1,r);
    	}
    	update(m);
    }
    int pre(int m,int l,int r){    //找最大值
    	if(t[m<<1|1].cnt){
    		return(pre(m<<1|1,mid+1,r));
    	}else if(l==r){
    		return(r);
    	}else{
    		return(pre(m<<1,l,mid));
    	}
    }
    long long call(int m,int x,int y,int l,int r){     //查询
    	if(x<=l&&r<=y){
    		return(t[m].mx);
    	}
    	pushdown(m);
    	long long re=0;
    	if(x<=mid){
    		re=call(m<<1,x,y,l,mid);
    	}
    	if(y>mid){
    		re=max(re,call(m<<1|1,x,y,mid+1,r));
    	}
    	update(m);
    	return(re);
    }
    int main(){
    	read(n);read(m);
    	for(int i=1;i<=n;i++){
    		read(a[i][0]);read(a[i][1]);
    		l[i]=&a[i][1];
    	}
    	for(int i=1;i<=m;i++){		
    		read(c[i][0]);read(c[i][1]);read(c[i][2]);
    		l[i+n]=&c[i][2];
    	}
    	sort(l+1,l+n+m+1,comp);
    	for(int i=1;i<n+m;i++){
    		if(*l[i]<*l[i+1]){
    			num[mx]=*l[i];
    			*l[i]=mx++;
    		}else{
    			*l[i]=mx;
    		}
    	}
    	num[mx]=*l[n+m];
    	*l[n+m]=mx;
    	for(int i=1;i<=mx;i++){
    		sg(1,i,i,num[i],1,mx);
    	}
    	for(int i=1;i<=n;i++){
    		sg(1,a[i][1]+1,mx,-a[i][0],1,mx);
    		point(1,a[i][1]+1,1,1,mx);
    	}
    	for(int i=1;i<=m;i++){
    		point(1,a[c[i][0]][1]+1,-1,1,mx);
    		sg(1,a[c[i][0]][1]+1,mx,a[c[i][0]][0],1,mx);
    		a[c[i][0]][0]=c[i][1];a[c[i][0]][1]=c[i][2];
    		point(1,a[c[i][0]][1]+1,1,1,mx);
    		sg(1,a[c[i][0]][1]+1,mx,-a[c[i][0]][0],1,mx);
    		printf("%lld
    ",call(1,1,pre(1,1,mx),1,mx));
    	}
    }
    
  • 相关阅读:
    python定时任务模块APScheduler
    from urllib import parse模块的使用
    go操作空指针导致supervisor进程服务挂机的坑
    docker快速安装rabbitmq
    利用redis的bitmap实现用户签到功能
    linux安装splunk-enterprise
    python封装email模块
    golang模块viper读取配置文件
    Tangram: Optimized Coarse-Grained Dataflow for Scalable NN Accelerators 阅读笔记
    将博客搬至CSDN
  • 原文地址:https://www.cnblogs.com/groundwater/p/13497330.html
Copyright © 2020-2023  润新知