树分治——边分治与边分树
边分治
「BZOJ 2870」最长道路tree
点击查看代码
#include
using namespace std;
int n,m;
int v[400005];
int ver[400005],ne[400005],head[400005],cnt=1,val[400005];
inline void link(int x,int y,int v){
ver[++cnt]=y;
ne[cnt]=head[x];
head[x]=cnt;val[cnt]=v;
}
vector son[200005];
void init(int x,int fi){
for(int i=head[x];i;i=ne[i]){
int u=ver[i];
if(u==fi)continue;
init(u,x);son[x].push_back(u);
}
}
inline void build(){
init(1,1);
for(int i=1;i<=n;i++)head[i]=0;cnt=1;
for(int i=1;i<=m;i++){
if(son[i].size()<3){
for(auto it:son[i]){
link(i,it,it<=n);link(it,i,it<=n);
}
}
else{
int le=++m,ri=++m;v[le]=v[ri]=v[i];
link(i,le,0);link(le,i,0);
link(i,ri,0);link(ri,i,0);
for(auto it:son[i])son[le].push_back(it),swap(le,ri);
}
}
}
int siz[200005],mxp[400005],rt;
bool vis[400005];
void findrt(int x,int fi,int tot){
siz[x]=1;
for(int i=head[x];i;i=ne[i]){
int u=ver[i];
if(vis[i]||u==fi)continue;
findrt(u,x,tot);siz[x]+=siz[u];
mxp[i>>1]=max(siz[u],tot-siz[u]);
if(mxp[rt]>mxp[i>>1])rt=(i>>1);
}
}
void dfs(int x,int fi,int mn,int dep,vector >&vec){
mn=min(mn,v[x]);
vec.push_back(make_pair(mn,dep));
for(int i=head[x];i;i=ne[i]){
int u=ver[i];
if(vis[i]||u==fi)continue;
dfs(u,x,mn,dep+val[i],vec);
}
}
long long ans;
void solve(int x){
mxp[rt=0]=n;findrt(x,x,siz[x]);
if(!rt)return ;
vis[rt<<1]=vis[rt<<1|1]=1;
int L=ver[rt<<1],R=ver[rt<<1|1];
vector >le,ri;
dfs(L,R,1e9,val[rt<<1],le);dfs(R,L,1e9,1,ri);
sort(le.begin(),le.end());reverse(le.begin(),le.end());
sort(ri.begin(),ri.end());reverse(ri.begin(),ri.end());
auto it1=le.begin();
int lenl=0,lenr=0;
for(auto it2:ri){
while(it1!=le.end()&&it1->first>=it2.first){
ans=max(ans,1ll*it1->first*(lenr+it1->second));
lenl=max(lenl,it1->second);it1++;
}
ans=max(ans,1ll*it2.first*(lenl+it2.second));
lenr=max(lenr,it2.second);
}
solve(L);solve(R);
}
int main(){
scanf("%d",&n);m=n;
memset(v,0x3f,sizeof(v));
for(int i=1;i<=n;i++)scanf("%d",&v[i]);
for(int i=1;i
「WC2010」重建计划
点击查看代码
#include
using namespace std;
int n,m;
int Lim,U;
int ver[400005],ne[400005],head[400005],cnt,val[400005];
inline void link(int x,int y,int v){
ver[++cnt]=y;
ne[cnt]=head[x];
head[x]=cnt;val[cnt]=v;
}
vector son[400005];
int pre[400005];
void init(int x,int fi){
for(int i=head[x];i;i=ne[i]){
int u=ver[i];
if(u==fi)continue;
pre[u]=val[i];
init(u,x);son[x].push_back(u);
}
}
inline void build(){
init(1,1);m=n;
for(int i=1;i<=n;i++)head[i]=0;cnt=1;
for(int i=1;i<=m;i++){
if(son[i].size()<3){
for(auto it:son[i])link(it,i,pre[it]),link(i,it,pre[it]);
}
else {
int le=++m,ri=++m;
link(i,le,0);link(le,i,0);
link(i,ri,0);link(ri,i,0);
for(auto it:son[i])son[le].push_back(it),swap(le,ri);
}
}
}
bool vis[400005];
int siz[400005],mxp[400005],rt;
void findrt(int x,int fi,int tot){
siz[x]=1;
for(int i=head[x];i;i=ne[i]){
int u=ver[i];
if(vis[i]||u==fi)continue;
findrt(u,x,tot);siz[x]+=siz[u];mxp[i>>1]=max(siz[u],tot-siz[u]);
if(mxp[i>>1]>1);
}
}
vector le,ri;
double mid,res;
void dfs(int x,int fi,int dep,double len,vector&vec,bool is=0){
if(is){
if(vec.size()<=dep)vec.push_back(len);
else vec[dep]=max(vec[dep],len);
}siz[x]=1;
for(int i=head[x];i;i=ne[i]){
int u=ver[i];
if(vis[i]||u==fi)continue;
dfs(u,x,dep+(val[i]!=0),len+val[i]-mid*(val[i]!=0),vec,is|(val[i]!=0));
siz[x]+=siz[u];
}
}
pair que[400005];
int top,ed;
void solve(int x,int tot){
mxp[rt=0]=m;findrt(x,x,tot);
if(!rt)return ;vis[rt<<1]=vis[rt<<1|1]=1;
int L=ver[rt<<1],R=ver[rt<<1|1];
le.clear();ri.clear();
dfs(L,R,0,0,le,1);dfs(R,L,(val[rt<<1]!=0)-1,val[rt<<1]-mid*(val[rt<<1]!=0),ri,(val[rt<<1]!=0));
top=1;ed=0;
for(int i=0,j=le.size()-1;i=0&&i+j+1>=Lim){
while(top<=ed&&que[ed].firstU)top++;
if(top<=ed)res=max(res,ri[i]+que[top].first);
}
solve(L,siz[L]);solve(R,siz[R]);
}
inline bool check(){
for(int i=1;i<=cnt;i++)vis[i]=0;res=-1e9;
solve(1,m);return res>=0;
}
int main(){
scanf("%d",&n);
scanf("%d%d",&Lim,&U);
for(int i=1;i
边分树
「PA2019」Podatki drogowe
点击查看代码
#include
using namespace std;
int n,m,lim;long long k;
vector rt1[400005],rt2[400005];
namespace Main{
int le[10000005],ri[10000005],siz[10000005],cnt;
unsigned long long tree[10000005],val[100005];
int insert(int loc,int y,int l=1,int r=n){
if(locr)return y;
int i=++cnt;tree[i]=tree[y]+val[loc];siz[i]=siz[y]+1;
if(l!=r){
int mid=(l+r)>>1;
le[i]=insert(loc,le[y],l,mid);ri[i]=insert(loc,ri[y],mid+1,r);
}
return i;
}
inline bool cmp(int a,int b,int c,int d){
int l=1,r=n;
while(l!=r){
int mid=(l+r)>>1;
if(tree[ri[a]]+tree[ri[b]]!=tree[ri[c]]+tree[ri[d]]){
l=mid+1;
a=ri[a];b=ri[b];c=ri[c];d=ri[d];
}else {
r=mid;
a=le[a];b=le[b];c=le[c];d=le[d];
}
}
return siz[a]+siz[b] L[400005],R[400005],pos[400005];
struct node{
int x,y;
node(int _x,int _y){
x=_x;y=_y;
}
inline bool operator <(const node &b)const{
return cmp(x,y,b.x,b.y);
}
};
long long ans,base=1;
const long long md=1e9+7;
void Get(int x,int y,int l=1,int r=n){
if(l==r){
base=base*n%md;ans=(ans+(siz[x]+siz[y])*base)%md;
return ;
}
int mid=(l+r)>>1;
Get(le[x],le[y],l,mid);Get(ri[x],ri[y],mid+1,r);
}
inline void main(){
long long all=0;
for(int i=1;i<=lim;i++){
L[i].resize(rt1[i].size());R[i].resize(rt1[i].size());pos[i].resize(rt1[i].size());
for(auto &it:R[i])it=rt2[i].size()-1;all+=1ll*rt1[i].size()*rt2[i].size();
}
node mid(0,0);
for(int t=1;t<=60;t++){
long long rk=abs(1ll*rand()*rand()+rand())%all+1;
for(int i=1;rk&&i<=lim;i++){
for(int j=0;j=rk){
mid=node(rt1[i][j],rt2[i][L[i][j]+rk-1]);
rk=0;break;
}else rk-=tmp;
}
}
long long tmp=0;
for(int i=1;i<=lim;i++){
int r=rt2[i].size()-1;
for(int j=0;j=L[i][j]&&mid > son[100005];
int las[100005];
void init(int x,int fi){
for(auto it:son[x]){
int u=it.first;if(u==fi)continue;
init(u,x);
if(!las[x])link(x,u,it.second),link(u,x,it.second),las[x]=x;
else {
link(las[x],++m,0);link(m,las[x],0);las[x]=m;
link(las[x],u,it.second);link(u,las[x],it.second);
}
}
}
int siz[200005],mxp[200005],root;
bool vis[400005];
void findrt(int x,int fi,int tot){
siz[x]=1;
for(int i=head[x];i;i=ne[i]){
int u=ver[i];if(vis[i]||u==fi)continue;
findrt(u,x,tot);siz[x]+=siz[u];mxp[i>>1]=max(tot-siz[u],siz[u]);
if(mxp[root]>mxp[i>>1])root=(i>>1);
}
}
int rt[200005];
vector vec;
void dfs(int x,int fi){
if(x<=n)vec.push_back(rt[x]);
siz[x]=1;
for(int i=head[x];i;i=ne[i]){
int u=ver[i];
if(vis[i]||u==fi)continue;
rt[u]=Main::insert(val[i],rt[x]);
dfs(u,x);siz[x]+=siz[u];
}
}
void solve(int x,int tot){
mxp[root=0]=m;findrt(x,x,tot);
if(!root)return ;vis[root<<1]=vis[root<<1|1]=1;
int L=ver[root<<1],R=ver[root<<1|1];++lim;
rt[L]=0;vec.clear();dfs(L,R);
sort(vec.begin(),vec.end(),Main::ccmp);swap(rt1[lim],vec);
rt[R]=Main::insert(val[root<<1],0);vec.clear();dfs(R,L);
sort(vec.begin(),vec.end(),Main::ccmp);swap(rt2[lim],vec);
solve(L,siz[L]);solve(R,siz[R]);
}
inline void main(){
for(int i=1;i<=n;i++)Main::val[i]=1ll*rand()*rand()*rand()+1ll*rand()*rand()+rand();
for(int i=1;i
CF757G Can Bash Save the Day?
点击查看代码
#include
using namespace std;
int n,m,q;
int ver[800005],ne[800005],head[400005],cnt=1;
long long val[800005];
inline void link(int x,int y,long long v){
ver[++cnt]=y;
ne[cnt]=head[x];
head[x]=cnt;val[cnt]=v;
}
vector son[800005];
long long fa[200005];
void init(int x,int fi){
for(int i=head[x];i;i=ne[i]){
int u=ver[i];
if(u==fi)continue;
fa[u]=val[i];
init(u,x);son[x].push_back(u);
}
}
inline void build(){
init(1,1);m=n;
for(int i=1;i<=n;i++)head[i]=0;cnt=1;
for(int i=1;i<=m;i++){
if(son[i].size()<3){
for(auto it:son[i])link(i,it,fa[it]),link(it,i,fa[it]);
}else {
int le=++m,ri=++m;
link(i,le,0);link(le,i,0);
link(i,ri,0);link(ri,i,0);
for(auto it:son[i])son[le].push_back(it),swap(le,ri);
}
}
}
int siz[400005],mxp[800005],rt;
bool vis[800005];
void findrt(int x,int fi,int tot){
siz[x]=1;
for(int i=head[x];i;i=ne[i]){
int u=ver[i];
if(vis[i]||u==fi)continue;
findrt(u,x,tot);siz[x]+=siz[u];
mxp[i>>1]=max(tot-siz[u],siz[u]);
// cout<"<>1]<mxp[i>>1])rt=(i>>1);
}
// cout< vec;
long long dep[400005];
void dfs(int x,int fi){
vec.push_back(x);
for(int i=head[x];i;i=ne[i]){
int u=ver[i];
if(vis[i]||u==fi)continue;
dep[u]=dep[x]+val[i];
dfs(u,x);
}
}
int le[12000005],ri[12000005],root[200005],lst[200005],all;
long long tree[12000005],sum[12000005];
void solve(int x){
mxp[rt=0]=n;findrt(x,x,siz[x]);
if(!rt)return ;vis[rt<<1]=vis[rt<<1|1]=1;
int L=ver[rt<<1],R=ver[rt<<1|1];
// cout<<"solve "<n)continue;
le[lst[it]]=++all;lst[it]=all;
tree[lst[it]]=dep[it];
}
vec.clear();dep[R]=0;dfs(R,L);
for(auto it:vec){
if(it>n)continue;
ri[lst[it]]=++all;lst[it]=all;
tree[lst[it]]=dep[it];
}
solve(L);solve(R);
}
int merge(int a,int b){
if(!a||!b)return a+b;
int i=++all;tree[i]=tree[a]+tree[b];sum[i]=sum[a]+sum[b];
le[i]=merge(le[a],le[b]);
ri[i]=merge(ri[a],ri[b]);
return i;
}
long long query(int x,int y){
// cout<
「GYM 102391」K. Wind of Change
点击查看代码
#include
using namespace std;
int n;
namespace T1{
int rt[1000005],le[50000005],ri[50000005],all;
long long tree[50000005],dep[1000005],ans[1000005];
inline void insert(int x,int y){
int now=rt[x];
while(1){
if(le[now]){
if(!le[y])le[y]=++all,tree[all]=1e18;
tree[le[y]]=min(tree[le[y]],tree[le[now]]+dep[x]);
now=le[now];y=le[y];
}else if(ri[now]){
if(!ri[y])ri[y]=++all,tree[all]=1e18;
tree[ri[y]]=min(tree[ri[y]],tree[ri[now]]+dep[x]);
now=ri[now];y=ri[y];
}else break;
}
}
inline void del(){
tree[all]=1e18;le[all]=ri[all]=0;all--;
}
inline long long query(int x,int y){
int now=rt[x];long long res=1e18;
while(1){
if(le[now]){
res=min(res,tree[le[now]]+dep[x]+tree[ri[y]]);
now=le[now];y=le[y];
}else if(ri[now]){
res=min(res,tree[ri[now]]+dep[x]+tree[le[y]]);
now=ri[now];y=ri[y];
}else break;
}
return res;
}
inline void calc(vector &le,vector &ri){
int tmp=all,rtl=++all,rtr=++all;
for(auto it:le)insert(it,rtl);
for(auto it:ri)insert(it,rtr);
for(auto it:le)ans[it]=min(ans[it],query(it,rtr));
for(auto it:ri)ans[it]=min(ans[it],query(it,rtl));
while(all>tmp)del();
}
int m;
int ver[2000005],ne[2000005],head[1000005],cnt,val[2000005];
inline void link(int x,int y,int v){
ver[++cnt]=y;
ne[cnt]=head[x];
head[x]=cnt;val[cnt]=v;
}
vector son[1000005];
int fa[1000005];
void init(int x,int fi){
for(int i=head[x];i;i=ne[i]){
int u=ver[i];
if(u==fi)continue;
fa[u]=val[i];
init(u,x);son[x].push_back(u);
}
}
inline void build(){
init(1,1);cnt=1;m=n;
for(int i=1;i<=n;i++)head[i]=0;
for(int i=1;i<=n;i++)ans[i]=1e18;
for(int i=1;i<=m;i++){
if(son[i].size()<3){
for(auto it:son[i])link(i,it,fa[it]),link(it,i,fa[it]);
}
else {
int le=++m,ri=++m;
link(i,le,0);link(le,i,0);
link(i,ri,0);link(ri,i,0);
for(auto it:son[i])son[le].push_back(it),swap(le,ri);
}
}
}
int siz[1000005],mxp[1000005],root;
bool vis[2000005];
void findrt(int x,int fi,int tot){
siz[x]=1;
for(int i=head[x];i;i=ne[i]){
int u=ver[i];
if(vis[i]||u==fi)continue;
findrt(u,x,tot);siz[x]+=siz[u];
mxp[i>>1]=max(tot-siz[u],siz[u]);
if(mxp[i>>1]>1);
}
}
vector vec;
void dfs(int x,int fi){
siz[x]=1;
for(int i=head[x];i;i=ne[i]){
int u=ver[i];
if(vis[i]||u==fi)continue;
dep[u]=dep[x]+val[i];dfs(u,x);siz[x]+=siz[u];
}if(x<=n)vec.push_back(x);
}
void solve(int x,int tot){
mxp[root=0]=m;findrt(x,x,tot);
if(!root)return ;vis[root<<1]=vis[root<<1|1]=1;
int L=ver[root<<1],R=ver[root<<1|1];
vec.clear();dep[L]=0;dfs(L,R);
vector le;swap(le,vec);
vec.clear();dep[R]=val[root<<1];dfs(R,L);calc(le,vec);
solve(L,siz[L]);solve(R,siz[R]);
}
inline void main(){
tree[0]=1e18;
for(int i=1;i son[2000005];
int fa[2000005],lst[1000005];
void init(int x,int fi){
for(int i=head[x];i;i=ne[i]){
int u=ver[i];
if(u==fi)continue;
fa[u]=val[i];
init(u,x);son[x].push_back(u);
}
}
inline void build(){
init(1,1);cnt=1;m=n;
for(int i=1;i<=n;i++)head[i]=0;
for(int i=1;i<=n;i++)T1::rt[i]=lst[i]=++T1::all;
for(int i=1;i<=m;i++){
if(son[i].size()<3){
for(auto it:son[i])link(i,it,fa[it]),link(it,i,fa[it]);
}
else {
int le=++m,ri=++m;
link(i,le,0);link(le,i,0);
link(i,ri,0);link(ri,i,0);
for(auto it:son[i])son[le].push_back(it),swap(le,ri);
}
}
}
int siz[1000005],mxp[1000005],rt;
bool vis[2000005];
void findrt(int x,int fi,int tot){
siz[x]=1;
for(int i=head[x];i;i=ne[i]){
int u=ver[i];
if(vis[i]||u==fi)continue;
findrt(u,x,tot);siz[x]+=siz[u];
mxp[i>>1]=max(tot-siz[u],siz[u]);
if(mxp[i>>1]>1);
}
}
long long dep[1000005];
vector vec;
void dfs(int x,int fi){
siz[x]=1;
for(int i=head[x];i;i=ne[i]){
int u=ver[i];
if(vis[i]||u==fi)continue;
dep[u]=dep[x]+val[i];dfs(u,x);siz[x]+=siz[u];
}if(x<=n)vec.push_back(x);
}
void solve(int x,int tot){
mxp[rt=0]=m;findrt(x,x,tot);
if(!rt)return ;vis[rt<<1]=vis[rt<<1|1]=1;
int L=ver[rt<<1],R=ver[rt<<1|1];
vec.clear();dep[L]=0;dfs(L,R);
for(auto it:vec){
T1::le[lst[it]]=++T1::all;lst[it]=T1::all;
T1::tree[lst[it]]=dep[it];
}
vec.clear();dep[R]=val[rt<<1];dfs(R,L);
for(auto it:vec){
T1::ri[lst[it]]=++T1::all;lst[it]=T1::all;
T1::tree[lst[it]]=dep[it];
}solve(L,siz[L]);solve(R,siz[R]);
}
inline void main(){
for(int i=1;i
「CTSC2018」暴力写挂
点击查看代码
#include
using namespace std;
#define int long long
int n,m;
int ans;
namespace T2{
int rt[800005],tree[80000005],le[80000005],ri[80000005],all;
int dep[800005];
int merge(int a,int b,int &res){
if(!a||!b)return a+b;
if(le[a]&&ri[b])res=max(res,tree[le[a]]+tree[ri[b]]);
if(ri[a]&&le[b])res=max(res,tree[ri[a]]+tree[le[b]]);
le[a]=merge(le[a],le[b],res);
ri[a]=merge(ri[a],ri[b],res);tree[a]=max(tree[a],tree[b]);
return a;
}
int ver[800005],ne[800005],head[800005],cnt,val[800005];
inline void link(int x,int y,int v){
ver[++cnt]=y;
ne[cnt]=head[x];
head[x]=cnt;val[cnt]=v;
}
void dfs(int x,int fi){
int res=-1e18;
for(int i=head[x];i;i=ne[i]){
int u=ver[i];
if(u==fi)continue;
dep[u]=dep[x]+val[i];
dfs(u,x);rt[x]=merge(rt[x],rt[u],res);
}
ans=max(ans,res-2*dep[x]);
}
}
namespace T1{
int ver[1600005],ne[1600005],head[1600005],cnt=1,val[1600005];
inline void link(int x,int y,int v){
ver[++cnt]=y;
ne[cnt]=head[x];
head[x]=cnt;val[cnt]=v;
}
int dep[800005],fa[800005];
vector son[800005];
void init(int x,int fi){
for(int i=head[x];i;i=ne[i]){
int u=ver[i];
if(u==fi)continue;
dep[u]=dep[x]+val[i];fa[u]=val[i];
init(u,x);son[x].push_back(u);
}
}
inline void build(){
init(1,1);m=n;
for(int i=1;i<=n;i++)head[i]=0;cnt=1;
for(int i=1;i<=m;i++){
if(son[i].size()<3){
for(auto it:son[i]){
link(i,it,fa[it]);link(it,i,fa[it]);
}
}else {
int le=++m,ri=++m;
link(i,le,0);link(le,i,0);
link(i,ri,0);link(ri,i,0);
for(auto it:son[i])son[le].push_back(it),swap(le,ri);
}
}
}
int siz[800005],mxp[800005],rt;
bool vis[1600005];
void findrt(int x,int fi,int tot){
siz[x]=1;
for(int i=head[x];i;i=ne[i]){
int u=ver[i];
if(vis[i]||u==fi)continue;
findrt(u,x,tot);siz[x]+=siz[u];
mxp[i>>1]=max(siz[u],tot-siz[u]);
if(mxp[i>>1]>1);
}
}
int dis[800005],lst[800005];
vector vec;
void dfs(int x,int fi){
vec.push_back(x);siz[x]=1;
for(int i=head[x];i;i=ne[i]){
int u=ver[i];
if(vis[i]||u==fi)continue;
dis[u]=dis[x]+val[i];
dfs(u,x);siz[x]+=siz[u];
}
}
void solve(int x){
mxp[rt=0]=n;findrt(x,x,siz[x]);
if(!rt)return ;vis[rt<<1]=vis[rt<<1|1]=1;
int L=ver[rt<<1],R=ver[rt<<1|1];
vec.clear();dis[L]=val[rt<<1];dfs(L,R);
for(auto it:vec){
if(it>n)continue;
T2::le[lst[it]]=++T2::all;lst[it]=T2::all;
T2::tree[lst[it]]=dis[it]+dep[it];
}
vec.clear();dis[R]=0;dfs(R,L);
for(auto it:vec){
if(it>n)continue;
T2::ri[lst[it]]=++T2::all;lst[it]=T2::all;
T2::tree[lst[it]]=dis[it]+dep[it];
}
solve(L);solve(R);
}
}
signed main(){
scanf("%lld",&n);
for(int i=1;i
「WC2018」通道
点击查看代码
#include
using namespace std;
int n;
struct Tree{
int ver[200005],ne[200005],head[200005],cnt;
long long val[200005];
inline void link(int x,int y,long long v){
ver[++cnt]=y;
ne[cnt]=head[x];
head[x]=cnt;val[cnt]=v;
}
long long dep[100005];
void dfs(int x,int fi){
for(int i=head[x];i;i=ne[i]){
int u=ver[i];
if(u==fi)continue;
dep[u]=dep[x]+val[i];
dfs(u,x);
}
}
Tree(){
for(int i=1;ires)res=tmp,nxt=i;
}x=nxt;if(vis[x])break;
}
}
printf("%lld",ans);
return 0;
}