求助关于淀粉质

P3806 【模板】点分治 1

Sad_Rex @ 2023-07-24 14:04:47


#include<bits/stdc++.h>
//#pragma GCC optimize(3, "Ofast,no-stack-protector,unroll-loops,fast-math")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4.1,sse4.2,avx,avx2,popcnt,tune=native")
using namespace std;
#define int long long
#define kg putchar(' ')
#define endl puts("")
inline int read(){
    int vis=1,ans=0;
    char x=getchar();
    while(x<'0'||x>'9'){
        if(x=='-')vis=-1;
        x=getchar();
    }
    while(x>='0'&&x<='9'){
        ans=ans*10+x-'0';
        x=getchar();
    }
    return vis*ans;
}
inline void print(int x){
    if(x<0)putchar('-'),x=-x;
    if(x>9)print(x/10);
    putchar(x%10+'0');
}
int n=read(),m=read();
const int N=1e4+9,M=1e8+9;
int u,v,w;
int minn=LONG_LONG_MAX;
struct node{
    int nxt,to,w;
}e[2*N];
int head[N],cnt;
inline void add(int x,int y,int w){
    ++cnt;
    e[cnt].to=y;
    e[cnt].nxt=head[x];
    e[cnt].w=w;
    head[x]=cnt;
}
int root,size[N],maxnson[N];
bool vis[N];
int tmp=0,dis[N];
int Sumnode;
int num[M];
inline void get_heavy(int p,int fa){
    size[p]=1,maxnson[p]=0;
    for(int i=head[p];i;i=e[i].nxt){
        int y=e[i].to;
        if(vis[y]||y==fa)continue;
        get_heavy(y,p);
        size[p]+=size[y];
        maxnson[p]=max(maxnson[p],size[y]);
    }
    maxnson[p]=max(maxnson[p],Sumnode-size[p]);
    if(maxnson[p]<minn)minn=maxnson[p],root=p;
}
inline void ask(int begin,int fa,int len){
    dis[++tmp]=len;
    for(int i=head[begin];i;i=e[i].nxt){
        int y=e[i].to;
        if(vis[y]||y==fa)continue;
        ask(y,begin,len+e[i].w);
    }
}
inline void init(int p,int len,bool f){
    tmp=0;
    ask(p,0,len);
    if(f==1){
        for(int i=1;i<tmp;i++){
            for(int j=i+1;j<=tmp;j++){
                num[dis[i]+dis[j]]++;
            }
        }
    }else if(f==0){
        for(int i=1;i<tmp;i++){
            for(int j=i+1;j<=tmp;j++){
                num[dis[i]+dis[j]]--;
            }
        }
    }
}
inline void difen(int p){
    vis[p]=1;
    init(p,0,1);
    for(int i=head[p];i;i=e[i].nxt){
        int y=e[p].to;
        if(vis[y])continue;
        init(y,e[i].w,0);
        minn=LONG_LONG_MAX,root=0,Sumnode=size[y];
        get_heavy(y,0);
        difen(root);
    }
}
signed main(){
//  freopen(".in","r",stdin);
//  freopen("SB.out","w",stdout);
    Sumnode=n;
    for(int i=1;i<n;i++){
        u=read(),v=read(),w=read();
        add(u,v,w),add(v,u,w);
    }
    get_heavy(1,0);
    difen(root);
    while(m--){
        int k=read();
        if(num[k])puts("AYE");
        else puts("NAY");
    }
    return 0;
}
/*
2 1
1 2 2
2
*/

by SSpider_Man @ 2023-10-18 14:50:50

问题有三:

1、y=e[p].to y=e[i].to

2、应该在计算dis(ask函数)时更新以当前重心为根的子树的size

3、询问离线,点分治常熟过大,会导致tle


by SSpider_Man @ 2023-10-18 14:51:20

@lovely_Rex


by SSpider_Man @ 2023-10-18 14:55:11

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e4+5;
const int maxv=1e7+5;
struct edge{
    int to,val;
};
int n,m,root,size[maxn],Bigchildsize,opt[maxn],ans[maxn],p,q[maxn];
bool vis[maxn];
int d[maxv];
vector<edge> e[maxn];
void findroot(int u,int fa,int tot){
    size[u]=1;
    int mxsize=0;
    for(int i=0;i<e[u].size();i++){
        int v=e[u][i].to;
        if(vis[v] || v==fa) continue;
        findroot(v,u,tot);
        mxsize=max(mxsize,size[v]);
        size[u]+=size[v]; 
    }
    mxsize=max(mxsize,tot-size[u]);
    if(mxsize<Bigchildsize){
        Bigchildsize=mxsize;
        root=u;
    }
}
void Getdis(int u,int fa,int dis){
    if(dis<=1e7) opt[++p]=dis;
    size[u]=1;
    for(int i=0;i<e[u].size();i++){
        int v=e[u][i].to;
        if(vis[v] || v==fa) continue;
        Getdis(v,u,dis+e[u][i].val);
        size[u]+=size[v];
    }
}
void calc(int l,int r){
    for(int i=l;i<=r;i++){
        for(int j=1;j<=m;j++){
             if(q[j]>=opt[i])
             ans[j]+=d[q[j]-opt[i]];
        }
    }
    for(int i=l;i<=r;i++)
        d[opt[i]]++;
}
void dec(){
    for(int i=1;i<=p;i++)
        d[opt[i]]--;
}
void solve(int u,int fa,int tot){
    root=u;
    Bigchildsize=tot;
    findroot(u,fa,tot);
    p=0;
    d[0]=1;
    opt[++p]=0;
    vis[root]=1;
    for(int i=0;i<e[root].size();i++){
        int v=e[root][i].to;
        if(vis[v]) continue;
        int pre=p;
        Getdis(v,root,e[root][i].val);
        calc(pre+1,p);
    }
    dec();
    int rt=root;
    for(int i=0;i<e[rt].size();i++){
        int v=e[rt][i].to;
        if(vis[v]) continue;
    //  cout<<v<<" "<<rt<<" "<<size[v]<<"\n";
        solve(v,rt,size[v]); 
    }
}
int main(){

    scanf("%d%d",&n,&m);
    for(int i=1;i<n;i++){
        int u,v,w;
        scanf("%d%d%d",&u,&v,&w);
        e[u].push_back((edge){v,w});
        e[v].push_back((edge){u,w});
    }
    for(int i=1;i<=m;i++)
        scanf("%d",&q[i]);
    solve(1,0,n);
    for(int i=1;i<=m;i++){
        if(ans[i]) printf("AYE\n");
        else printf("NAY\n");
    }
    return 0;
}

by SSpider_Man @ 2023-10-18 14:55:51

第三部没做,所以T了


|