傳送門:
這是一道好題,不容易想到線段樹和維護的量。
分析題目,考慮聯通方式,發現只有3種,我一開始的想法是結構分塊,使用並查集維護,o(1)新增很自然,刪除的話就暴力重建塊內的並查集o(sqrt(n)),查詢的時候仍然考慮並查集維護,求出關鍵點(上下左右4個)和他們之間的聯通性,數量級是o(sqrt(n))的,這一步複雜度自然也是o(nsqrt(n))的,然而這樣還不夠科學。
當然,另一種分塊方式比較奇特(!!!),對詢問分塊,每次暴力重建並查集,刪除的邊看做不存在,這樣重建sqrt(n)次,每次複雜度o(n),這一步複雜度o(nsqrt(n)),重建後對於每次操作新增詢問塊內改變的o(sqrt(n))條邊,但每次完成後要消除影響,這一步比較麻煩可以用遞迴完成,回溯的時候修改並查集的對應值,單次查詢o(sqrt(n)),這樣總複雜度:o(nsqrt(n)),對詢問分塊然後暴力重建是常用的分塊套路,然而這仍然不狗科學,我們看上去需要乙個log級別的演算法,考慮到行數較少只有2,我們選擇用線段樹維護連通性。
想到線段樹,一切就很明顯了,類似於dp,維護四個邊界點的連通性6個量,這是可合併的,注意查詢的時候3種方式,複雜度:o(nlog(n))
#include
#include
#include
#include
#define n 100000
using
namespace
std;
struct node;
int n;
node s[5],a[(n<<2)+5];
bool
map[(n<<2)+5];
inline
int calc(int x,int y)
inline
int getnum()
void init();
s[1] = (node);
memset(map,0,sizeof(map));
memset(a,0,sizeof(a));
}inline
void build(int l,int r,int rt)
build(l,mid,rt<<1);
build(mid+1,r,rt<<1|1);
}inline node merge(node a,node b,bool x,bool y)
inline
void insert(int l,int r,int rt,int x1,int y1,int x2,int y2,bool c)
else
if (x1!=x2&&l==r)
if (y<=mid) insert(l,mid,rt<<1,x1,y1,x2,y2,c);
if (y>mid) insert(mid+1,r,rt<<1|1,x1,y1,x2,y2,c);
a[rt] = merge(a[rt<<1],a[rt<<1|1],map[calc(0,mid)],map[calc(1,mid)]);
}inline node query(int l,int r,int rt,int ll,int rr)
inline
void ask(int x1,int y1,int x2,int y2)
void do_it()
}int main()
分塊**(!!!):
總結:1.注意用位運算減少分情況討論數量,減少**量
2.寫較繁瑣的程式之前一定想好每個細節然後再寫
3.嘗試一題多解並code,不要偷懶
sb問題:如果將修改和刪除改為一整行呢?
BZOJ 1018 堵塞的交通 線段樹維護連通性
rightarrow 戳我進bzoj原題 time limit 3 sec quad memory limit 162 mb有一天,由於某種穿越現象作用,你來到了傳說中的小人國。小人國的布局非常奇特,整個國家的交通系統可以被看成是乙個 2 行 c 列的矩形網格,網格上的每個點代表乙個城市,相鄰的城市...
BZOJ 1018 線段樹維護連通性
這個題我總是想用迴圈完成轉移,最後發現,還是手工列舉最靠譜 建立線段樹,線段樹的每個節點 代表的是區間 維護以上六個值,true表示連通,false表示不連通,具體可以看我的 view code 1 include 2 include 3 include 4 include 5 include 6 ...
2017 9 9 堵塞的交通 思考記錄
三分太難了 於是來寫線段樹 維護四個點之間的連通性 然後就沒了。然後把n定義成bool 狂wa不止 以後資料結構題不寫對拍就不要交!你一定要足夠的相信你的程式很多地方都是錯的 碼 include includeusing namespace std define zuo o 1,l,mid defi...