bzoj 1018 堵塞的交通

2021-07-10 07:16:48 字數 1770 閱讀 9909

傳送門:

這是一道好題,不容易想到線段樹和維護的量。

分析題目,考慮聯通方式,發現只有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...