[bzoj4364] [IOI2014]wall磚墻
Description
健佳正在用大小相同的磚塊來砌起一面墻。這面墻由 列磚塊所組成,它們從左到右的編號0至n-1。各列的高度可
以不同。各列的高度就是該列磚塊的數量。健佳用如下方式來建造這面墻。最開始每列都沒有磚塊。此後,健佳通
過k個階段的增加(adding)或移除(removing)磚塊操作來砌墻。當所有k個階段完成後,這面墻就砌好了。在每個階
段中,健佳都會被告知一個連續的磚塊列的範圍,以及一個高度值h,然後他就完成如下過程:在增加磚塊(adding
)階段,對於給定的列範圍中高度小於h的列,健佳會增加磚塊使它們的高度都恰好等於h。此時他不會改變那些高
度大於或等於h的列。在移除磚塊(removing)階段,對於給定的列範圍中高度大於 的列,健佳會移除磚塊使它們的
高度都恰好等於h。此時他不會改變那些高度小於或等於h的列。你的任務就是計算出這面墻的最後形狀。
Input
第1行:n, k。
第2+i 行(0≤i≤k-1):op[i], left[i], right[i], height[i]。
n: 這面墻中的列數。
k: 階段數。
op: 大小為k的數組;op[i]是第i個階段的類型:1 表示增加階段(adding) 而 2表示移除階段(removing)
其中0≤i≤k-1。
left 和 right: 大小為k的數組;在第i個階段中,列的範圍從第left[i] 列開始到第right[i]列結束(包括兩端
left[i] 和 right[i]),其中0≤i≤k-1。這裏保證滿足left[i]≤right[i]。
height: 大小為k的數組;height[i] 表示在階段i的高度參數,其中0≤i≤k-1。
Output
共n行
第i行包含一個整數表示finalHeight[i]。
finalHeight: 大小為n的數組;你需要把第i列磚塊的最終數量存放到finalHeight[i]中做為返回結果
其中0≤i≤n-1。
Solution
orz吉司機論文
線段樹模板題
記錄下最大值次大值,最大值作為標記下傳,如果當前要修改的最大值影響不到次大值就改下最大值,否則暴力dfs,復雜度\(O(m\log^2 n)?\),具體見2016年論文。
#include<bits/stdc++.h> using namespace std; void read(int &x) { x=0;int f=1;char ch=getchar(); for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f; for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f; } const int maxn = 2e6+10; const int inf = 1e9; int n,m; #define ls p<<1 #define rs p<<1|1 #define mid ((l+r)>>1) struct Segment_Tree { int mn[maxn<<2],mx[maxn<<2],smx[maxn<<2],smn[maxn<<2]; void update(int p) { if(mx[ls]==mx[rs]) mx[p]=mx[ls],smx[p]=max(smx[ls],smx[rs]); else if(mx[ls]>mx[rs]) mx[p]=mx[ls],smx[p]=max(smx[ls],mx[rs]); else mx[p]=mx[rs],smx[p]=max(smx[rs],mx[ls]); if(mn[ls]==mn[rs]) mn[p]=mn[ls],smn[p]=min(smn[ls],smn[rs]); else if(mn[ls]>mn[rs]) mn[p]=mn[rs],smn[p]=min(smn[rs],mn[ls]); else mn[p]=mn[ls],smn[p]=min(smn[ls],mn[rs]); } void build(int p,int l,int r) { if(l==r) return mn[p]=mx[p]=0,smn[p]=inf,smx[p]=-inf,void(); build(ls,l,mid),build(rs,mid+1,r),update(p); } void push_max(int p,int x) { mx[p]=x;mn[p]=min(mn[p],x); if(mx[p]==mn[p]) smx[p]=-inf,smn[p]=inf; else smn[p]=min(smn[p],x); } void push_min(int p,int x) { mn[p]=x,mx[p]=max(mx[p],x); if(mx[p]==mn[p]) smx[p]=-inf,smn[p]=inf; else smx[p]=max(smx[p],x); } void pushdown(int p) { if(mx[ls]>mx[p]&&mx[p]>smx[ls]) push_max(ls,mx[p]); if(mx[rs]>mx[p]&&mx[p]>smx[rs]) push_max(rs,mx[p]); if(mn[ls]<mn[p]&&mn[p]<smn[ls]) push_min(ls,mn[p]); if(mn[rs]<mn[p]&&mn[p]<smn[rs]) push_min(rs,mn[p]); } void add(int p,int l,int r,int x,int y,int z) { if(mn[p]>=z) return ; if(x<=l&&r<=y&&z<smn[p]) return push_min(p,z),void(); pushdown(p); if(x<=mid) add(ls,l,mid,x,y,z); if(y>mid) add(rs,mid+1,r,x,y,z); update(p); } void remove(int p,int l,int r,int x,int y,int z) { if(mx[p]<=z) return ; if(x<=l&&r<=y&&smx[p]<z) return push_max(p,z),void(); pushdown(p); if(x<=mid) remove(ls,l,mid,x,y,z); if(y>mid) remove(rs,mid+1,r,x,y,z); update(p); } void print(int p,int l,int r) { if(l==r) return printf("%d\n",mx[p]),void(); pushdown(p); print(ls,l,mid),print(rs,mid+1,r); } }SGT; int main() { read(n),read(m);SGT.build(1,1,n); for(int op,x,y,z,i=1;i<=m;i++) { read(op),read(x),read(y),read(z);x++,y++; if(op==1) SGT.add(1,1,n,x,y,z); else SGT.remove(1,1,n,x,y,z); } SGT.print(1,1,n); return 0; }
[bzoj4364] [IOI2014]wall磚墻