夏吉巴乱搞按链分块的块状树
Posted caturra
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了夏吉巴乱搞按链分块的块状树相关的知识,希望对你有一定的参考价值。
我感觉可以开\(O(\sqrt{n})\)棵01字典树来做省赛C题
目前处于测试阶段
#include<bits/stdc++.h>
#define rep(i,j,k) for(register int i=j;i<=k;i++)
#define rrep(i,j,k) for(register int i=j;i>=k;i--)
#define erep(i,u) for(register int i=head[u];~i;i=nxt[i])
#define print(a) printf("%lld",(ll)(a))
#define println(a) printf("%lld\n",(ll)(a))
#define printbk(a) printf("%lld ",(ll)(a))
using namespace std;
const int MAXN = 1e5+11;
typedef long long ll;
ll read(){
ll x=0,f=1;register char ch=getchar();
while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}
while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
return x*f;
}
int to[MAXN<<1],nxt[MAXN<<1],head[MAXN<<1],tot;
int val[MAXN],depth[MAXN],belong[MAXN];
void init(){
memset(head,-1,sizeof head);
tot=0;
}
void add(int u,int v){
to[tot]=v;
nxt[tot]=head[u];
head[u]=tot++;
}
struct BLOCK{
int block[3003][3003],size[3003],cnt,limit;
int _from[6006],_to[6006],_nxt[6006],_head[3003],_tot;
void _add(int u,int v){
_to[_tot]=v;
_from[_tot]=u;
_nxt[_tot]=_head[u];
_head[u]=_tot++;
}
void init(int lmt){
size[0]=cnt=_tot=0;
limit=lmt;
memset(_head,-1,sizeof _head);
}
void build(int u,int fa,int d){
depth[u]=d;
if(fa==-1){
belong[u]=++cnt;
block[cnt][++size[cnt]]=u;
}else{
int id=belong[fa];
int tail=block[id][size[id]];
if(tail==fa&&size[id]<=limit){
belong[u]=id;
block[id][++size[id]]=u;
}else{
belong[u]=++cnt;
block[cnt][++size[cnt]]=u;
_add(cnt,belong[fa]);
}
}
erep(i,u){
int v=to[i];
if(v==fa) continue;
build(v,u,d+1);
}
}
void out(int n){
rep(i,1,n){
cout<<"id: "<<i<<" blockID: "<<belong[i]<<" size: "<<size[belong[i]]<<endl;
}
cout<<endl;
//for(int i=_head[1]; ~i; i=_nxt[i]){
//int v=_to[i];
//cout<<_from[i]<<"-->"<<_to[i]<<endl;
//}
}
}b;
int main(){
int n;
while(cin>>n){
init();
rep(i,1,n-1){
int u=read();
int v=read();
add(u,v);
add(v,u);
}
// rep(i,1,n) val[i]=read();
b.init(sqrt(n)+1);
b.build(1,-1,1);
b.out(n);
}
}
/*
15
1 2
2 3
3 4
2 5
1 6
6 7
7 8
8 9
9 13
13 15
13 14
8 10
10 11
11 12
*/
改良版
#include<bits/stdc++.h>
#define rep(i,j,k) for(register int i=j;i<=k;i++)
#define rrep(i,j,k) for(register int i=j;i>=k;i--)
#define erep(i,u) for(register int i=head[u];~i;i=nxt[i])
#define print(a) printf("%lld",(ll)(a))
#define println(a) printf("%lld\n",(ll)(a))
#define printbk(a) printf("%lld ",(ll)(a))
using namespace std;
const int MAXN = 1e5+11;
typedef long long ll;
ll read(){
ll x=0,f=1;register char ch=getchar();
while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}
while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
return x*f;
}
int to[MAXN<<1],nxt[MAXN<<1],head[MAXN<<1],tot;
int val[MAXN],depth[MAXN],belong[MAXN],treesize[MAXN],son[MAXN];
void init(){
memset(head,-1,sizeof head);
tot=0;
}
void add(int u,int v){
to[tot]=v;
nxt[tot]=head[u];
head[u]=tot++;
}
struct BLOCK{
vector<int> block[MAXN];
// int block[3003][3003],size[3003],
int cnt,limit;
int _from[MAXN],_to[MAXN],_nxt[MAXN],_head[MAXN],_tot;
void _add(int u,int v){
_to[_tot]=v;
_from[_tot]=u;
_nxt[_tot]=_head[u];
_head[u]=_tot++;
}
void init(int lmt,int n){
rep(i,1,n) block[i].clear();
cnt=_tot=0;
limit=lmt;
memset(_head,-1,sizeof _head);
}
void prepare(int u,int fa,int d){
depth[u]=d; treesize[u]=1; son[u]=-1;
erep(i,u){
int v=to[i];
if(v==fa) continue;
prepare(v,u,d+1);
treesize[u]+=treesize[v];
if(son[u]==-1||treesize[v]>treesize[son[u]]) son[u]=v;
}
}
void build(int u,int fa){
if(fa==-1){
belong[u]=++cnt;
block[cnt].push_back(u);
}else{
int id=belong[fa];
int sz=block[id].size();
int tail=block[id][sz-1];
if(tail==fa&&sz<=limit&&son[fa]==u){
belong[u]=id;
block[id].push_back(u);
}else{
belong[u]=++cnt;
block[cnt].push_back(u);
_add(cnt,belong[fa]);
}
}
erep(i,u){
int v=to[i];
if(v==fa) continue;
build(v,u);
}
}
void build(int root){
prepare(root,-1,1);
build(root,-1);
}
void out(int n){
rep(i,1,n){
cout<<"id: "<<i<<" blockID: "<<belong[i]<<" size: "<<block[belong[i]].size()<<endl;
}
cout<<endl;
for(int i=_head[5]; ~i; i=_nxt[i]){
int v=_to[i];
cout<<_from[i]<<"-->"<<_to[i]<<endl;
}
}
}b;
int main(){
int n;
while(cin>>n){
init();
rep(i,1,n-1){
int u=read();
int v=read();
add(u,v);
add(v,u);
}
// rep(i,1,n) val[i]=read();
b.init(sqrt(n)+1,n);
b.build(1);
b.out(n);
}
}
以上是关于夏吉巴乱搞按链分块的块状树的主要内容,如果未能解决你的问题,请参考以下文章