1. 程式人生 > >cogs265.線段覆蓋

cogs265.線段覆蓋

open 操作類 pan lin () 兩個 題解 限制 線段樹

265. 線段覆蓋

★★★☆ 輸入文件:xdfg.in 輸出文件:xdfg.out 簡單對比
時間限制:2 s 內存限制:20 MB

【問題描述】

有一根長度為 L 的白色條狀物。有兩種操作:

  1. 用一條長度為 T 的黑布蓋住條狀物的 [a, a+T] 這個區間 (0<=a, T<=L) 。
  2. 把某條黑布拿走。

輸入 L 和 n 次操作,要你輸出每次操作之後:

  1. 條狀物上有多少個黑區間。
  2. 條狀物上黑區間的總長度。

【輸入格式】

輸入文件第一行兩個整數L(1<=L<=200000), n(1<=n<=200000)

以下有n行,第2--n+1行每行有3個整數m,a,T,m表示操作類型,1表示放入黑布,2表示拿走黑布,a,T表示黑布在L上的起始位置與長度,拿走的黑布保證是原來已經存在的.

【輸出格式】

輸出有n行,每行兩個整數x,y,x表示L上的黑區間個數,y表示黑區間的總長度.

【輸入輸出樣例】

輸入:

20 4
1 5 3
1 7 2
2 5 3
1 16 3

輸出:

1 3
1 4
1 2
2 5

[題解]

線段樹維護區間被覆蓋長度 段數 被覆蓋層數 "左融合" "右融合";由此可以實現每次O(1)查詢;

解釋:所謂左右融合其實就是判斷用的,左右融合就是字面意思,能否與左邊右邊的黑布融合,用於數據上傳;

本題難在兩點:

1.數據上傳的時候,通過"左融合" "右融合"現實處理計算區間段數:

由兒子上傳數據時,當前區間的段數等於左兒子的段數加右兒子的段數,

難點在於:如果左兒子最右邊是被黑布蓋著,右兒子左邊是被黑布蓋著,顯然段數多算了1,

而左右融合此時的作用體現了,若左兒子右融合等於1,右兒子左融合等於1,那麽此節點段數需要減1,正確性,,很顯然啊....

2.(我之前就一直卡在這裏)

本來我想用lazy下傳黑布,後來發現不可做...必須每次操作具體到葉子,於是T了很多點,

後來發現這個題有個特點, 撤走的黑布一定存在!

那麽就不需要lazy下傳了,只需要維護區間被蓋了幾次

撤走黑布就把蓋的次數-1;

當被覆蓋0次那麽所有數據清空;

否則保留.

於是,A了.

[代碼]

#include <cstdio>
#include <algorithm>
using
namespace std; int n,t; struct d { int len,s; int zr,yr; int c; }; d node[400000]; inline void gengxin(int o,int l,int r) { if(node[o].c>0) { node[o].zr=node[o].yr=node[o].s=1; node[o].len=r-l+1; return; } else { node[o].zr=node[o*2].zr; node[o].yr=node[o*2+1].yr; node[o].len=node[o*2].len+node[o*2+1].len; node[o].s=node[o*2].s+node[o*2+1].s; if(node[o*2].yr==1&&node[o*2+1].zr==1)node[o].s--; return ; } } inline void add(int o,int l,int r,int nl,int nr,int v) { if(l>=nl&&r<=nr) { node[o].c+=v; if(l==r) { if(node[o].c>0) { node[o].len=node[o].zr=node[o].yr=node[o].s=1; return; } else { node[o].len=node[o].zr=node[o].yr=node[o].s=0; return; } } else { gengxin(o,l,r); return; } } int m=(l+r)>>1; if(m>=nl) { add(o*2,l,m,nl,nr,v); } if(m<nr) { add(o*2+1,m+1,r,nl,nr,v); } gengxin(o,l,r); } int main() { freopen("xdfg.in","r",stdin); freopen("xdfg.out","w",stdout); scanf("%d%d",&n,&t); while(t--) { int x,y,z; scanf("%d%d%d",&x,&y,&z); if(x==1) { add(1,1,n,y,y+z-1,1); } else { add(1,1,n,y,y+z-1,-1); } printf("%d %d\n",node[1].s,node[1].len); } return 0; }

cogs265.線段覆蓋