zoukankan      html  css  js  c++  java
  • 点分治

    这怕是noip的考试范围哦。Achen在半年前就会了的算法我现在都不会。


    自己比较智障,连写3道题都是get_root()之后就去solve(z)而不是solve(root),搞得又T又RE

    点分治模板(洛谷)

    //Serene
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    #include<set>
    using namespace std;
    #define ll long long
    #define db double
    #define For(i,a,b) for(int i=(a);i<=(b);++i)
    #define Rep(i,a,b) for(int i=(a);i>=(b);--i)
    const int maxn=1e4+7;
    int n,m,ans[maxn],p[maxn];
    int size[maxn],son[maxn],sumsize,root,vis[maxn],len[maxn];
    
    char cc; ll ff;
    template<typename T>void read(T& aa) {
        aa=0;cc=getchar();ff=1;
        while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
        if(cc=='-') ff=-1,cc=getchar();
        while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
        aa*=ff;
    }
    int fir[maxn],nxt[2*maxn],to[2*maxn],v[2*maxn],e=0;
    void add(int x,int y,int z) {
        to[++e]=y;nxt[e]=fir[x];fir[x]=e;v[e]=z;
        to[++e]=x;nxt[e]=fir[y];fir[y]=e;v[e]=z;
    }
    
    void get_root(int pos,int f) {
        size[pos]=1; son[pos]=0; int y,z;
        for(y=fir[pos];y;y=nxt[y]) {
            if((z=to[y])==f||vis[z]) continue;
            get_root(z,pos);
            size[pos]+=size[z];
            son[pos]=max(son[pos],size[z]);
        }
        son[pos]=max(son[pos],sumsize-size[pos]);
        if(son[pos]<son[root]) root=pos;
    }
    
    set<int> G;
    int zz[maxn],t;
    void get_ans(int x) {
        For(i,1,m) if(G.find(p[i]-x)!=G.end()) ans[i]|=1;
    }
    
    void dfs(int pos,int f) {
        int y,z; zz[++t]=len[pos];
        get_ans(len[pos]);
        for(y=fir[pos];y;y=nxt[y]) {
            if(vis[z=to[y]]||z==f) continue;
            len[z]=len[pos]+v[y]; dfs(z,pos);
        }
    }
    
    void solve(int pos) {
        vis[pos]=1; G.clear(); G.insert(0);
        int y,z;
        for(y=fir[pos];y;y=nxt[y]) {
            if(vis[z=to[y]]) continue;
            len[z]=v[y]; dfs(z,pos);
            while(t) G.insert(zz[t--]);
        }
        for(y=fir[pos];y;y=nxt[y]) {
            if(vis[z=to[y]]) continue;
            sumsize=size[z]; root=0;
            get_root(z,0);solve(root);
        } 
    }
    
    int main() {
        read(n); read(m);
        int x,y,z;
        For(i,1,n-1) {
            read(x); read(y); read(z);
            add(x,y,z);
        }
        For(i,1,m) read(p[i]);
        son[root=0]=sumsize=n; get_root(1,0); solve(root);
        For(i,1,m) printf(ans[i]? "AYE
    ":"NAY
    ");
        return 0;
    }
    

      

    bzoj2152聪聪可可

    //Serene
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    #define ll long long
    #define db double
    #define For(i,a,b) for(int i=(a);i<=(b);++i)
    #define Rep(i,a,b) for(int i=(a);i>=(b);--i)
    const int maxn=4e4+7;
    int n,root,vis[maxn],nowsum;
     
    char cc; ll ff;
    template<typename T>void read(T& aa) {
        aa=0;cc=getchar();ff=1;
        while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
        if(cc=='-') ff=-1,cc=getchar();
        while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
        aa*=ff;
    }
     
    ll gcd(ll x,ll y) {
        return y==0? x:gcd(y,x%y);
    }
     
    int fir[maxn],nxt[2*maxn],to[2*maxn],e=0,v[2*maxn];
    void add(int x,int y,int z) {
        to[++e]=y;nxt[e]=fir[x];fir[x]=e;v[e]=z%3;
        to[++e]=x;nxt[e]=fir[y];fir[y]=e;v[e]=z%3;
    }
     
    int son[maxn],size[maxn];
    void get_root(int pos,int f) {
        size[pos]=1; son[pos]=0; int y,z;
        for(y=fir[pos];y;y=nxt[y]) {
            if((z=to[y])==f||vis[z]) continue;
            get_root(z,pos);
            size[pos]+=size[z];
            if(size[z]>=son[pos]) son[pos]=size[z];
        }
        son[pos]=max(son[pos],nowsum-size[pos]);
        if(son[pos]<son[root]) root=pos;
    }
     
    ll ans;
    ll now[10],tot[10],t;
    void dfs(int pos,int f,int x) {
        ++now[x]; int y,z;
        ans+=2*tot[(3-x)%3];
        for(y=fir[pos];y;y=nxt[y]) {
            if(vis[z=to[y]]||z==f) continue;
            dfs(z,pos,(x+v[y])%3);
        }
    }
     
    void solve(int pos) {
        vis[pos]=1; int y,z;
        memset(tot,0,sizeof(tot)); tot[0]=1;
        for(y=fir[pos];y;y=nxt[y]) {
            if(vis[z=to[y]]) continue;
            dfs(z,pos,v[y]%3);
            For(i,0,2) tot[i]+=now[i],now[i]=0;
        }
        for(y=fir[pos];y;y=nxt[y]) {
            if(vis[z=to[y]]) continue;
            nowsum=size[z]; root=0;
            get_root(z,pos); solve(root);
        }
    }
     
    int main() {
        read(n); int x,y,z; ans=n;
        For(i,1,n-1) {
            read(x); read(y); read(z);
            add(x,y,z);
        }
        size[0]=son[0]=nowsum=n;
        get_root(1,0); solve(root);
        ll r=n*n;ll p=gcd(ans,r);
        ans/=p; r/=p;
        printf("%lld/%lld",ans,r);
        return 0;
    }
    

      

    bzoj3648寝室管理

    裸的点分治,环的处理就是直接把环跑一遍就可以了。

    //Serene
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    #define ll long long
    #define db double
    #define For(i,a,b) for(int i=(a);i<=(b);++i)
    #define Rep(i,a,b) for(int i=(a);i>=(b);--i)
    const int maxn=1e5+7;
    int n,m,k,A,B,root,SUM;
    ll ans;
    
    char cc; ll ff;
    template<typename T>void read(T& aa) {
    	aa=0;cc=getchar();ff=1;
    	while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
    	if(cc=='-') ff=-1,cc=getchar();
    	while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
    	aa*=ff;
    }
    
    int f[maxn];
    int find(int x){return x==f[x]? x:f[x]=find(f[x]);}
    
    int fir[maxn],nxt[2*maxn],to[2*maxn],e=0;
    void add(int x,int y) {
    	to[++e]=y;nxt[e]=fir[x];fir[x]=e;
    	to[++e]=x;nxt[e]=fir[y];fir[y]=e;
    }
    
    int sz[maxn];
    void chge(int pos,int x) {
    	while(pos<=n) {
    		sz[pos]+=x;
    		pos+=pos&-pos;
    	}
    }
    
    int q(int pos) {
    	ll rs=0;
    	while(pos) {
    		rs+=sz[pos];
    		pos-=pos&-pos;
    	}
    	return rs;
    }
    
    int size[maxn],U[maxn];bool vis[maxn];
    void get_root(int pos,int f) {
    	int y,z;U[pos]=0;size[pos]=1;
    	for(y=fir[pos];y;y=nxt[y]) {
    		if((z=to[y])==f||vis[z]) continue;
    		get_root(z,pos);
    		size[pos]+=size[z];
    		U[pos]=max(U[pos],size[z]);
    	}
    	U[pos]=max(U[pos],SUM-size[pos]);
    	if(U[pos]<U[root]) root=pos;
    }
    
    int zz[maxn],s,t;
    void dfs(int pos,int f,int d,int dd) {//d:push dd:query
    	zz[++t]=d; int y,z;
    	ans+=(ll)q(n)-q(max(k-dd-1,0));
    	for(y=fir[pos];y;y=nxt[y]) {
    		if((z=to[y])==f||vis[z]) continue;
    		dfs(z,pos,d+1,dd+1);
    	}
    }
    
    void solve(int pos) {
    	vis[pos]=1; int y,z;
    	zz[s=t=1]=1;chge(1,1);
    	for(y=fir[pos];y;y=nxt[y]) {
    		if(vis[z=to[y]]) continue;
    		dfs(z,pos,2,1);
    		For(i,s+1,t) chge(zz[i],1);
    		s=t;
    	}
    	For(i,1,t) chge(zz[i],-1);
    	for(y=fir[pos];y;y=nxt[y]) {
    		if(vis[z=to[y]]) continue;
    		SUM=size[z]; root=0; get_root(z,pos);
    		solve(root);
    	}
    }
    
    int h[maxn],tot;
    bool get_h(int pos,int f) {
    	h[++tot]=pos; int y,z;
    	if(pos==B) return vis[pos]=1;
    	for(y=fir[pos];y;y=nxt[y]) {
    		if((z=to[y])==f) continue;
    		if(get_h(z,pos)) return vis[pos]=1;
    	}
    	tot--;
    	return 0;
    }
    
    void get_ans() {
    	memset(vis,0,sizeof(vis));
    	tot=0;s=t=0; get_h(A,0);
    	For(r,1,tot) {
    		dfs(h[r],0,r,tot-r+1);
    		For(i,s+1,t) chge(zz[i],1);
    		s=t;
    	}
    }
    
    int main() {
    	read(n); read(m); read(k);
    	int x,y;
    	For(i,1,n) f[i]=i;
    	For(i,1,m) {
    		read(x); read(y);
    		if(find(x)==find(y)) A=x,B=y;
    		else {
    			f[find(x)]=find(y);
    			add(x,y);
    		}
    	}
    	U[0]=n+1; SUM=n; 
    	get_root(1,0); solve(root);
    	if(n==m) get_ans();
    	printf("%lld",ans);
    	return 0;
    }
    /*
    5 5 2
    1 3
    2 4
    3 5
    4 1
    5 2
    */
    

      

  • 相关阅读:
    序列化二叉树
    把二叉树打印成多行
    按之字形顺序打印二叉树
    对称的二叉树
    二叉树的下一个节点
    java ee项目用gradle依赖打包
    spring cloud gateway 拦截request Body
    oauth2学习
    docker 应用
    gradle spring 配置解释
  • 原文地址:https://www.cnblogs.com/Serene-shixinyi/p/8575588.html
Copyright © 2011-2022 走看看