Codeforces Round 905 (Div. 1) C. Minimum Array(在线+贪心map / 离线+扫描线思想+区间删除)

题目

长为n(n<=5e5)的数组a,第i个数ai(-1e9<=ai<=1e9)

q(q<=5e5)次操作,每次选择一个区间[l,r],对这个区间加x(-1e9<=x<=1e9)

求序列操作前及第[1,q]次操作后,这q+1次对应的序列中,

历史最小字典序是哪个序列,输出序列

实际为t(t<=5e5)组样例,sumn和sumq均不超过5e5

思路来源

夏老师代码

HHU_zZhu代码

题解1(在线)

在线就是直接考虑保留第几次操作后是最优答案

考虑已经有一个最优答案,怎么替换成一个更优的答案,

肯定是最优答案,从某个前缀位置开始,有一个单点减,使这个点变得更小了

那区间减也可以维护成若干个差分,

如果若干次操作后,差分的第一个位置是一个单点减,说明是可以替换成更优的答案

所以map维护区间差分的位置,把map上差分为0的项实时抹掉,

去判断第一个差分非0的最左项是正还是负的,是负的说明可以保留,更新答案

题解2(离线)

扫描线思想, 把[0,q]这q+1个时间戳拍到线段树上,让这q+1个位置同时从第一个位置开始比

n个位置,q个时刻,扫描线,增序扫n个位置,l加,r+1减

在扫描线区间内的位置,即被若干次修改覆盖,

在某个时间区间对应+x,另一个时间区间对应-y,...,

保留区间加对应的最小的那个时间区间

每个修改是有时间后效性的,也就是第i时刻的修改,会改[i,q]时间的值

只关注最小值即可,删掉不可能成为最小值的时刻,这些时刻一定是在前缀某个位置处变大了

维护区间最小值,删掉的置成INF,保证经过后面的操作这些也不可能成为最小即可

代码1(在线)

cpp 复制代码
//#include <bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<vector>
#include<map>
using namespace std;
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define per(i,a,b) for(int i=(a);i>=(b);--i)
typedef long long ll;
typedef double db;
typedef pair<int,int> P;
#define fi first
#define se second
#define pb push_back
#define dbg(x) cerr<<(#x)<<":"<<x<<" ";
#define dbg2(x) cerr<<(#x)<<":"<<x<<endl;
#define SZ(a) (int)(a.size())
#define sci(a) scanf("%d",&(a))
#define pt(a) printf("%d",a);
#define pte(a) printf("%d\n",a)
#define ptlle(a) printf("%lld\n",a)
#define debug(...) fprintf(stderr, __VA_ARGS__)
using namespace std;
const int N=5e5+10;
map<int,ll>mp;
array<int,3>op[N];
int t,n,q,pos,a[N],l,r,w;
ll add[N];
int main(){
    sci(t);
    while(t--){
        sci(n);
        mp.clear();
        pos=0;
        rep(i,1,n){
            sci(a[i]);
            add[i]=0;
        }
        sci(q);
        rep(i,1,q){
            sci(l),sci(r),sci(w);
            op[i]={l,r,w};
            mp[l]+=w;
            mp[r+1]-=w;
            if(!mp[l])mp.erase(mp.find(l));
            if(!mp[r+1])mp.erase(mp.find(r+1));
            if(mp.size() && mp.begin()->se<0){
                pos=i;
                mp.clear();
            }
        }
        rep(i,1,pos){
            auto [l,r,w]=op[i];
            add[l]+=w;
            add[r+1]-=w;
        }
        rep(i,1,n){
            add[i]+=add[i-1];
        }
        rep(i,1,n){
            printf("%lld%c",a[i]+add[i]," \n"[i==n]);
        }
    }
    return 0;
}

代码2(离线)

cpp 复制代码
//#include <bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define per(i,a,b) for(int i=(a);i>=(b);--i)
typedef long long ll;
typedef double db;
typedef pair<int,int> P;
#define fi first
#define se second
#define pb push_back
#define dbg(x) cerr<<(#x)<<":"<<x<<" ";
#define dbg2(x) cerr<<(#x)<<":"<<x<<endl;
#define SZ(a) (int)(a.size())
#define sci(a) scanf("%d",&(a))
#define pt(a) printf("%d",a);
#define pte(a) printf("%d\n",a)
#define ptlle(a) printf("%lld\n",a)
#define debug(...) fprintf(stderr, __VA_ARGS__)
using namespace std;
const int N=5e5+10;
const ll INF=1e18,INF2=1e17;
typedef pair<int,int> P;
struct segtree{
	int n;
	struct node{int l,r;ll c,mn,mx;}e[N<<2];
	#define l(p) e[p].l
	#define r(p) e[p].r
	#define mn(p) e[p].mn
	#define mx(p) e[p].mx
	#define c(p) e[p].c
	void up(int p){
        mn(p)=min(mn(p<<1),mn(p<<1|1));
        mx(p)=max(mx(p<<1),mx(p<<1|1));
    }
	void bld(int p,int l,int r){
		l(p)=l;r(p)=r;
        mn(p)=mx(p)=c(p)=0;
		if(l==r){return;}
		int mid=l+r>>1;
		bld(p<<1,l,mid);bld(p<<1|1,mid+1,r);
		up(p);
	}
	void psd(int p){
		if(c(p)){
			mn(p<<1)+=c(p);
			mx(p<<1)+=c(p);
			c(p<<1)+=c(p);
			mn(p<<1|1)+=c(p);		
			mx(p<<1|1)+=c(p);
            c(p<<1|1)+=c(p);
			c(p)=0; 
		}
	}
	void init(int _n){n=_n;bld(1,0,n);}
    void add(int p,int ql,int qr,int v){
        if(mn(p)>=INF2)return;
		if(ql<=l(p)&&r(p)<=qr){
			mn(p)+=v;
            mx(p)+=v;
			c(p)+=v;
			return;
		}
		psd(p);
		int mid=l(p)+r(p)>>1;
		if(ql<=mid)add(p<<1,ql,qr,v);
		if(qr>mid)add(p<<1|1,ql,qr,v);
		up(p);
	}
	void del(int p,int ql,int qr,ll v){// 每一个要删的递归到底,均摊O(nlogn)
        if(mn(p)>=INF2)return;
        if(l(p)==r(p) && mx(p)>v){
            mn(p)=INF;
            mx(p)=-INF;
            return;
        }
		psd(p);
		int mid=l(p)+r(p)>>1;
		if(ql<=mid && mx(p<<1)>v)del(p<<1,ql,qr,v);// 左区间有要删的
		if(qr>mid && mx(p<<1|1)>v)del(p<<1|1,ql,qr,v);// 右区间又要删的
		up(p);
	}
	ll ask(int p,int ql,int qr){
        if(mn(p)>=INF2)return INF2;
		if(ql<=l(p)&&r(p)<=qr)return mn(p);
		int mid=l(p)+r(p)>>1;
        ll res=INF2;
		psd(p);
		if(ql<=mid)res=min(res,ask(p<<1,ql,qr));
		if(qr>mid)res=min(res,ask(p<<1|1,ql,qr));
		return res;
	}
}seg;
int t,n,a[N],q,l,r,w;
vector<P>add[N],del[N];
ll ans[N];
int main(){
    sci(t);
    while(t--){
        sci(n);
        rep(i,1,n){
            sci(a[i]);
            add[i].clear();
            del[i].clear();
        }
        sci(q);
        seg.init(q);
        rep(i,1,q){
            sci(l),sci(r),sci(w);
            add[l].pb(P(i,w));
            del[r].pb(P(i,w));
        }
        rep(i,1,n){
            for(auto &x:add[i]){
                //printf("i:%d x.fi:%d x.se:%d\n",i,x.fi,x.se);
                seg.add(1,x.fi,q,x.se);
            }
            ll mn=seg.ask(1,0,q);
            ans[i]=mn+a[i];
            seg.del(1,0,q,mn);
            for(auto &x:del[i]){
                seg.add(1,x.fi,q,-x.se);
            }
        }
        rep(i,1,n){
            printf("%lld%c",ans[i]," \n"[i==n]);
        }
    }
    return 0;
}
相关推荐
硕风和炜7 天前
【LeetCode: 1338. 数组大小减半 + 哈希表 + 贪心】
算法·leetcode·散列表·贪心·哈希表
硕风和炜15 天前
【LeetCode: 316. 去除重复字母 + 栈 + 哈希表】
java·算法·leetcode·散列表·贪心··哈希表
我是哈哈hh19 天前
专题二十四_贪心策略(2)_算法专题详细总结
数据结构·c++·算法·leetcode·贪心算法·贪心
sweetheart7-719 天前
LeetCode763. 划分字母区间(2024冬季每日一题 23)
算法·力扣·贪心
闻缺陷则喜何志丹24 天前
【C++贪心 数论】991. 坏了的计算器|1909
c++·算法·力扣·数论·贪心·计算器·最小
一直学习永不止步1 个月前
LeetCode题练习与总结:最长回文串--409
java·数据结构·算法·leetcode·字符串·贪心·哈希表
Tisfy1 个月前
LeetCode 3244.新增道路查询后的最短距离 II:贪心(跃迁合并)-9行py(O(n))
算法·leetcode·题解·贪心·思维
wqqqianqian1 个月前
国产linux系统(银河麒麟,统信uos)使用 PageOffice 实现word文件在线留痕
word·在线·uos·国产·银河麒麟·pageoffice·痕迹
wqqqianqian2 个月前
国产linux系统(银河麒麟,统信uos)使用 PageOffice 在线打开Word文件最简单集成代码
java·vue·word·在线·pageoffice·国产linux
xiangshangdemayi2 个月前
vue3环境下mapbox本地部署极速入门
部署·矢量切片·mapbox·内网·离线·天地图