记录

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;
}

附录

DP

挂分详情

DS

posted @ 2024-08-20 15:48  exut  阅读(2)  评论(0编辑  收藏  举报
Title