记录
8.15~now
学习淀粉树(done)
写板子(done)
P4178 Tree
非容斥版本(done),容斥和非容斥版本的区别在于非容斥在当前节点 \(u\) 统计的是各个子树的答案,容斥统计的是自己这个子树的答案,会重复。推荐写容斥。
和板子没啥区别,桶改树状数组(非容斥)或上双指针(容斥) 就可以了
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+5;
const int inf=1000000005;
int hd[N],tot;
int n,m;
int K;
int ans;
struct edge{
int v,nxt,w;
}e[N*2];
void add(int u,int v,int w){
e[++tot]={v,hd[u],w};
hd[u]=tot;
}
int msz[N];
int siz[N];
bool vis[N];
int dis[N];
int B[N];
int sum;
int rt;
void G(int u,int fa){//get root
siz[u]=1,msz[u]=0;
for(int i=hd[u];i;i=e[i].nxt){
int v=e[i].v;
if(v==fa or vis[v]) continue;
G(v,u);
siz[u]+=siz[v];
msz[u]=max(msz[u],siz[v]);
}
msz[u]=max(msz[u],sum-siz[u]);
if(msz[u]<msz[rt]) rt=u;
}
void D(int u,int fa,int len){//get dis
B[++B[0]]=len;
for(int i=hd[u];i;i=e[i].nxt){
int v=e[i].v;
if(v==fa or vis[v]) continue;
D(v,u,len+e[i].w);
}
}
int Q[N];
int calc(int u,int W){
B[0]=0;
D(u,0,W);
sort(B+1,B+B[0]+1);
int l=1,r=B[0],sum=0;
for(;;l++){
while(r and B[l]+B[r]>K) r--;
if(l>r) break;
sum+=r-l+1;
}
return sum;
}
void div(int u){//分治
vis[u]=1;
ans+=calc(u,0);
for(int i=hd[u];i;i=e[i].nxt){
int v=e[i].v;
if(vis[v]) continue;
ans-=calc(v,e[i].w);
sum=siz[v];
msz[rt=0]=inf;
G(v,0);
div(rt);
}
}
signed main(){
cin>>n;
for(int i=1,u,v,w;i<n;i++){
cin>>u>>v>>w;
add(u,v,w);
add(v,u,w);
}
cin>>K;
msz[rt]=sum=n;
G(1,0);
div(rt);
cout<<ans-n;
}
CF293E
升级版的P4178,改成了二维偏序。
用容斥版本,然后在 \(calc()\) 函数用双指针和树状数组作掉两维偏序,就可以了。
P5351 Ruri Loves Maschera
容斥版本,在计算时把存下来的链(存最大权)按魔力值排序,扫一次用树状数组维护 \(LR\) 的约束
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e6+5;
const int inf=1000000005;
int hd[N],tot;
int n,m;
int K;
int L,R;
int ww;
struct BIT{
int S[N];
void ins(int x){x++;for (int i = x; i <= n + 1; i += (i&(-i))){S[i]++;}}
void del(int x){x++;for (int i = x; i <= n + 1; i += (i&(-i))){S[i]--;}}
int QU(int x,int ass=0){x++;if(x<=0)return 0;for (int i = x; i; i -= (i&(-i))){ass+=S[i];}return ass;}
}s;
int ans;
struct edge{
int v,nxt,w;
}e[N*2];
void add(int u,int v,int w){
e[++tot]={v,hd[u],w};
hd[u]=tot;
}
struct node{
int len,dep;
};
int msz[N];
int siz[N];
bool vis[N];
int dis[N];
node B[N];
int sum;
int rt;
void G(int u,int fa){//get root
siz[u]=1,msz[u]=0;
for(int i=hd[u];i;i=e[i].nxt){
int v=e[i].v;
if(v==fa or vis[v]) continue;
G(v,u);
siz[u]+=siz[v];
msz[u]=max(msz[u],siz[v]);
}
msz[u]=max(msz[u],sum-siz[u]);
if(msz[u]<msz[rt]) rt=u;
}
int cnt;
void D(int u,int fa,int len,int bs){//get dis
B[++cnt]={len,bs};
for(int i=hd[u];i;i=e[i].nxt){
int v=e[i].v;
if(v==fa or vis[v]) continue;
D(v,u,max(len,e[i].w),bs+1);
}
}
int Q[N];
bool cmp(node x,node y){
if (x.len!=y.len) return x.len<y.len;
return x.dep<y.dep;
}
int calc(int u,int W,int bs){
cnt=0;
D(u,0,W,bs);
sort(B+1,B+cnt+1,cmp);
int sum=0;
for(int i=1;i<=cnt;i++){
sum+=B[i].len*(s.QU(R-B[i].dep)-s.QU(L-B[i].dep-1));
s.ins(B[i].dep);
}
for(int i=1;i<=cnt;i++) {
s.del(B[i].dep);}
return sum;
}
void div(int u){//分治
vis[u]=1;
ans+=calc(u,0,0);
for(int i=hd[u];i;i=e[i].nxt){
int v=e[i].v;
if(vis[v]) continue;
ans-=calc(v,e[i].w,1);
sum=siz[v];
msz[rt=0]=inf;
G(v,0);
div(rt);
}
}
signed main(){
cin>>n>>L>>R;
for(int i=1,u,v,w;i<n;i++){
cin>>u>>v>>w;
add(u,v,w);
add(v,u,w);
}
msz[rt]=sum=n;
G(1,0);
div(rt);
cout<<ans*2;
}
P2634
上点分治比较板子,不如来玩玩 DSU
点击查看代码
#include<bits/stdc++.h>
#define ei for(int i=hd[x],v;i;i=e[i].nxt)
using namespace std;
const int N=4e4+5;
int n;
struct edge{
int v,w,nxt;
}e[N];
int hd[N],tot;
void link(int u,int v,int w){
e[++tot]={v,w,hd[u]},hd[u]=tot;
}
int siz[N],son[N],dep[N];
void dson(int x,int fa){
siz[x]=1;
ei{
if((v=e[i].v)^fa){
dep[v]=dep[x]+e[i].w;dep[v]%=3;
dson(v,x);
siz[x]+=siz[v];
if(siz[son[x]]<siz[v]) son[x]=v;
}
}
}
int ton[4];
int ans;
void cal(int S,int M){
int x=(2*dep[M]-dep[S])%3+3;
x=x%3;
ans+=ton[x];
}
void run(int x,int fa,bool kp,int rt){
if(kp) cal(x,rt);
else ton[dep[x]]++;
ei{
if((v=e[i].v)^fa) run(v,x,kp,rt);
}
}
void dsu(int x,int fa,bool kp){
ei if((v=e[i].v)^fa and v^son[x]) dsu(v,x,0);
if(son[x]) dsu(son[x],x,1);
ei{
if((v=e[i].v)^fa and v^son[x]){
run(v,x,1,x);
run(v,x,0,x);
}
}
cal(x,x);
ton[dep[x]]++;
if(kp^1)
ton[0]=ton[1]=ton[2]=0;
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>n;
for(int i=1,u,v,w;i<n;i++){
cin>>u>>v>>w;w%=3;
link(u,v,w);
link(v,u,w);
}
dson(1,0);
dsu(1,0,0);
ans=ans*2+n;
int a=ans,b=n*n,c;
c=__gcd(a,b);
cout<<a/c<<"/"<<b/c;
}
附录