BZOJ3648 寢室管理(點分治 bit)

2021-07-27 00:13:20 字數 2368 閱讀 3808

傳送門

sunshine學長去年的互測題orz

然而他給的solution除了點分和bit什麼都沒說啊。。。

硬著頭皮想吧,反正我知道要用bit了。。

如果是樹的話點分治+二分或者bit就能搞定

如果是環套樹的話怎麼辦捏

首先考慮不經過環的答案,直接在外向樹上點分就行了

然後考慮經過環的答案

假設當前外向樹上深度為h的有x個點,那麼上一棵外向樹的貢獻就是x*深度》=k-1-h的點的個數

假設上乙個外向樹深度為1,2,..的點的個數都加入到bit裡,那麼就直接在bit裡查詢就可以了

從這裡可以想到用bit來維護然後查詢,也就是將當前外向樹之前的點都加進去,暴力列舉當前外向樹的深度,然後查詢

當然兩棵外向樹的距離是不一樣的,所以在加入的過程中還需要根據距離進行相應的差分,實際上就是後乙個加入的深度相比實際深度要比前乙個小

還有就是因為是乙個環,需要展環成鏈然後做n次

細節比較多。。。

時間複雜度o(

nlog

n∗一坨

常數)

有乙個讓我掛挺了的地方,,就是點分治必須每一次更新size,否則找到的重心是不準確的

#include

#include

#include

#include

#include

#include

using

namespace

std;

#define ll long long

#define n 200005

#define base 200000

int n,m,k,x,y;

int tot,point[n],nxt[n*2],v[n*2];

void addedge(int x,int y)

namespace tree

big[x]=max(big[x],sum-size[x]);

if (big[x]void getdeep(int x,int fa)

}int find(int l,int r,int x)

return ans;

}ll calc(int x,int now)

return t;

}void dfs(int x)

}void solve()

}namespace cir_tree

}void circle(int x,int y)

c[++c[0]]=y;

for (int i=1;i<=c[0];++i) vis[c[i]]=1;

for (int i=1;i<=c[0];++i) findsizeh(c[i],0);

}void findc(int x,int fa)

findc(v[i],x);

}if (flag) return;

}void getroot(int x,int fa)

big[x]=max(big[x],sum-size[x]);

if (big[x]void getdeep(int x,int fa)

}int find(int l,int r,int x)

return ans;

}ll calc(int x,int now)

return t;

}void dfs(int x)

}void add(int loc,int val)

int query(int loc)

void sel(int x,int fa)

}void addh(int x,int y,int z)

void solve()

memset(vis,0,sizeof(vis));

for (int i=1;i<=c[0];++i) vis[c[i]]=1;

++k;

memset(c,0,sizeof(c));

for (int i=1;i<=c[0];++i)

}for (int i=1;i<=c[0];++i) c[i+c[0]]=c[i];

for (int i=1;i0];++i)

for (int i=0;i0];++i)

for (int j=pth[c[c[0]+i]];j;j=nxth[j])

for (int j=pth[c[c[0]+i]];j;j=nxth[j])

add(vh[j]-(c[0]+i-1)+base,ch[j]);

}printf("%lld\n",ans);

}}int main()

if (m==n-1) tree::solve();

else cir_tree::solve();

}

專案36 4 血型統計

任務和 黑貓警長在犯罪現場發現了一些血跡,現已經委託檢驗機構確定了血型,需要統計各種血型的樣本數目。輸入 血型序列 a b o c,c代表ab型血,輸入以x結束 輸出 各種血型的數量 輸入樣例 abcaocoaoobx 輸出樣例 a 3 b 2 o 4 ab 2 檔名 main.c 完成日期 201...

nyoj364田忌賽馬

題意 和古代的田忌賽馬一樣,只是可以有多匹馬 大體思路用貪心,主要 盡量多贏幾場 這就有兩點 1.贏的時候盡量贏差不多的對手 2.實在贏不了,就去消耗對方高手 include include using namespace std int t 10000 int k 10000 int main v...

NYOJ 364 田忌賽馬

題意 田忌和齊王各有n匹馬,判斷怎樣比賽,使田忌淨勝場數最多。我感覺這題的精髓就是,不管怎麼比賽,都要讓田忌的馬發揮最大價值。當然,馬的第一要務是用來贏得比賽,而且要最大效益的贏,也就是要贏對方僅次於自己的馬。當他不能完成這個任務的時候就要去輸,並拉對方最快的馬下水,給自己後面的隊友創造更大的勝利機...