hdu 4467 Graph 莫隊演算法思想

2021-07-14 12:39:03 字數 1299 閱讀 5216

題目連線:hdu_4467_graph

題意:給你n個點,m條邊,每條邊有乙個權值,有兩個操作,乙個是修改單點的顏色,乙個是詢問邊的兩個端點都為指定顏色的權值和

題解:這題如果暴力的話,就是維護3個ans,乙個是兩個端點都為0的,乙個是乙個為1乙個為0的,最後還有個兩個端點都為1的,對於每個詢問,可以做到o(1),但對於修改單點操作,極限狀態下,乙個單點的邊最大可為1e5,這樣果斷t飛,如果我們對每個單點修改做到o(1),那麼詢問的時候會達到1e5*1e5,也果斷t飛,怎麼辦,這時候想想莫隊的思想,將這兩個操作的時間複雜度均分一下,我們設乙個點的邊大於sqrt(m)的為重點,小於的為輕點,這樣我們對輕點進行暴力維護就sqrt(m),重點就將他周圍的權值用乙個二維陣列sum[i][j]維護,表示i這個重點它周圍的j這個顏色的權值和,每次修改重點時,直接在三個ans上對sum加加減減就行了,當修改輕點的時候要注意,輕點周圍的重點的sum要維護一下,設重點(邊大於sqrt(m))的個數為x,則x*sqrt(m)/2

#include#include#include#include#define f(i,a,b) for(int i=a;i<=b;i++)

typedef long long ll;

using namespace std;

const int n=(int)1e5+7;

int du[n],sp[n],type[n],g[n][2],v[n<<2],nxt[n<<2],ed,sqr;

ll ans[3],w[n<<2],sum[n][2];

//sp表示為輕重點(邊數大於sqr的為重點),type為當前的型別

struct edge

//將邊去重並將權值合併

sort(e,e+m);

int cnt=0;

for(int i=0,j;i=sqr);

memset(g,0,sizeof(g)),ed=0;

f(i,0,cnt-1)

memset(ans,0,sizeof(ans)),memset(sum,0,sizeof(sum));

//維護每一種ans和重點周圍的邊的權值和

f(i,0,cnt-1)

printf("case %d:\n", ic++);

int q,a,b,x;char s[20];

scanf("%d",&q);

while(q--)

}else

}//更新重點的sum

for(int i=g[x][1];i;i=nxt[i])

}} }

return 0;

}

HDU 4467 Graph(莫隊思想)

題意 給你n個點,m條邊,每條邊有乙個權值,有兩個操作,乙個是修改單點的顏色 顏色只有0,1兩種 乙個是詢問邊的兩個端點都為指定顏色的權值和。思路 由於每個點的顏色只有0,1兩種,那麼答案只有3種情況 00,01,11 用乙個陣列維護即可。即ans 0 統計邊的兩端都是0的權值和,ans 1 統計邊...

HDU4467 Graph 點的度數分塊

給出一張n個點m條邊的無向圖,點的顏色為0 1,每次有兩種操作 1.asksum x y,查詢兩點顏色為x和y的邊的權值之和 2.change x,將x顏色取反 最直接的做法是每次改變點的顏色豆漿與該點所連的邊更新,o q m 超時 那麼我們考慮將點根據度數分類,將度數 的點稱為普通點,否則為超級點...

HDU6287 口算訓練(莫隊演算法)

小q非常喜歡數學,但是他的口算能力非常弱。因此他找到了小t,給了小t乙個長度為 nn 的正整數序列 a1 a2,ana1,a2,an 要求小t丟擲 mm 個問題以訓練他的口算能力。每個問題給出三個正整數 l,r,dl,r,d 小q需要通過口算快速判斷 al al 1 ar 1 a ral al 1 ...