cf1108E2 线段树类似扫描线
Posted zsben991126
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了cf1108E2 线段树类似扫描线相关的知识,希望对你有一定的参考价值。
/* 有点像扫描线 思路:从左到右枚举每个点,枚举到点i时,把所有以i为起点的区间的影响删去 再加上以i-1为结尾的区间的影响 */ #include<bits/stdc++.h> using namespace std; #define maxn 200005 #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 int n,m,a[maxn]; struct Inv{int l,r;}p[400]; int lazy[maxn<<2],Min[maxn<<2]; inline void pushup(int rt){ Min[rt]=min(Min[rt<<1],Min[rt<<1|1]); } inline void pushdown(int rt){ if(lazy[rt]){ lazy[rt<<1]+=lazy[rt];lazy[rt<<1|1]+=lazy[rt]; Min[rt<<1]+=lazy[rt];Min[rt<<1|1]+=lazy[rt]; lazy[rt]=0; } } void build(int l,int r,int rt){ lazy[rt]=0; if(l==r){Min[rt]=a[l];return;} int m=l+r>>1; build(lson); build(rson); pushup(rt); } void update(int L,int R,int l,int r,int rt,int val){ if(L<=l && R>=r){ Min[rt]+=val,lazy[rt]+=val;return; } pushdown(rt); int m=l+r>>1; if(L<=m)update(L,R,lson,val); if(R>m)update(L,R,rson,val); pushup(rt); } int query(int L,int R,int l,int r,int rt){ if(L<=l&&R>=r){return Min[rt];} pushdown(rt); int m=l+r>>1,res=99999999; if(L<=m)res=min(res,query(L,R,lson)); if(R>m)res=min(res,query(L,R,rson)); pushup(rt); return res; } vector<int>ans[100005]; int main(){ cin>>n>>m; for(int i=1;i<=n;i++)scanf("%d",&a[i]); for(int i=1;i<=m;i++)scanf("%d%d",&p[i].l,&p[i].r); int Max=-1,index=0; build(1,n,1); for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ if(p[j].l<=i&&p[j].r>=i){//该区间和当前坐标有关 if(i!=1 && !(p[j].l<=i-1&&p[j].r>=i-1))//和左边结点无关 update(p[j].l,p[j].r,1,n,1,1);//加上这段的值 continue; } ans[i].push_back(j); //算上之前没算上的区间 if(i==1 || p[j].l<=i-1&&p[j].r>=i-1) update(p[j].l,p[j].r,1,n,1,-1); } int tmp=query(1,n,1,n,1); if(a[i]-tmp>Max){index=i;Max=a[i]-tmp;} } cout << Max << endl; cout << ans[index].size()<<endl; for(int i=0;i<ans[index].size();i++) cout << ans[index][i]<< " "; }
以上是关于cf1108E2 线段树类似扫描线的主要内容,如果未能解决你的问题,请参考以下文章
CF #535 (Div. 3) E2 Array and Segments (Hard version) 利用线段树进行区间转移
CF538H Summer Dichotomy 二分图扫描线线段树