码迷,mamicode.com
首页 > 其他好文 > 详细

点分治

时间:2016-08-21 15:08:51      阅读:139      评论:0      收藏:0      [点我收藏+]

标签:

树上奇奇怪怪的算法真是多...

 
简单学一下点分治,记录一下题和题解。
 
点分治入门/模板题
 
不多说。
//POJ 1741
//by Cydiater
//2016.8.17
#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#include <map>
#include <ctime>
#include <cmath>
#include <cstdlib>
#include <iomanip>
#include <cstdio>
using namespace std;
#define ll long long
#define up(i,j,n)       for(int i=j;i<=n;i++)
#define down(i,j,n)     for(int i=j;i>=n;i--)
const int MAXN=1e5+5;
const int oo=0x3f3f3f3f;
inline int read(){
      char ch=getchar();int x=0,f=1;
      while(ch>9||ch<0){if(ch==-)f=-1;ch=getchar();}
      while(ch>=0&&ch<=9){x=x*10+ch-0;ch=getchar();}
      return x*f;
}
int N,K,LINK[MAXN],len=0,root,siz[MAXN],dis[MAXN],ms[MAXN],sum,ans,dep[MAXN],q[MAXN],head,tail;
bool vis[MAXN];
struct edge{int y,next,v;}e[MAXN];
namespace solution{
      inline void insert(int x,int y,int v){e[++len].next=LINK[x];LINK[x]=len;e[len].y=y;e[len].v=v;}
      void init(){
            if(N==0&&K==0)exit(0);
            len=0;ans=0;
            memset(LINK,0,sizeof(LINK));
            memset(siz,0,sizeof(siz));
            memset(vis,0,sizeof(vis));
            memset(dis,0,sizeof(dis));
            memset(dep,0,sizeof(dep));
            memset(ms,0,sizeof(ms));
            up(i,1,N-1){
                  int x=read(),y=read(),v=read();
                  insert(x,y,v);
                  insert(y,x,v);
            }
      }
      void getroot(int node,int fa){
            siz[node]=1;ms[node]=0;
            for(int i=LINK[node];i;i=e[i].next)
                  if(!vis[e[i].y]&&e[i].y!=fa){
                        getroot(e[i].y,node);
                        siz[node]+=siz[e[i].y];
                        ms[node]=max(ms[node],siz[e[i].y]);
                  }
            ms[node]=max(ms[node],sum-siz[node]);
            if(ms[node]<ms[root])root=node;
      }
      void getdeep(int node,int fa){
            q[++tail]=dis[node];
            for(int i=LINK[node];i;i=e[i].next)
                  if(!vis[e[i].y]&&e[i].y!=fa){
                        dis[e[i].y]=dis[node]+e[i].v;
                        getdeep(e[i].y,node);
                  }
      }
      int col(int node,int di){
            int tmp=0;
            dis[node]=di;head=1;tail=0;
            getdeep(node,0);
            sort(q+1,q+tail+1);
            while(head<tail){
                  while(q[head]+q[tail]>K&&head<tail)tail--;
                  tmp+=tail-head;
                  head++;
            }
            return tmp;
      }
      void work(int node){
            ans+=col(node,0);
            vis[node]=1;
            for(int i=LINK[node];i;i=e[i].next)
                  if(!vis[e[i].y]){
                        ans-=col(e[i].y,e[i].v);
                        sum=siz[e[i].y];
                        root=0;
                        getroot(e[i].y,node);
                        work(root);
                  }
      }
      void slove(){
            root=0;sum=N;ms[0]=oo;
            getroot(1,0);
            work(root);
      }
      void output(){
            printf("%d\n",ans);
      }
}
int main(){
      //freopen("input.in","r",stdin);
      using namespace solution;
      while(scanf("%d %d",&N,&K)!=EOF){
            init();
            slove();
            output();
      }
      return 0;
}
写的时候犯傻了 
O(N^2)的验证我竟然真写上去了 mdzz
 
验证的时候统计一下mod3==1 mod3==2 mod3==0
然后乱搞一下就好了
 
剩下的就是普通的点分治
//BZOJ 2152
//by Cydiater
//2016.8.17
#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#include <map>
#include <ctime>
#include <cstdio>
#include <cstdlib>
#include <iomanip>
#include <cmath>
using namespace std;
#define ll long long
#define up(i,j,n)       for(int i=j;i<=n;i++)
#define down(i,j,n)     for(int i=j;i>=n;i--)
const int MAXN=1e5+5;
const int oo=0x3f3f3f3f;
inline int read(){
      char ch=getchar();int x=0,f=1;
      while(ch>9||ch<0){if(ch==-)f=-1;ch=getchar();}
      while(ch>=0&&ch<=9){x=x*10+ch-0;ch=getchar();}
      return x*f;
}
int N,LINK[MAXN],len=0,ms[MAXN],siz[MAXN],ans=0,root=0,sum,dis[MAXN],q[MAXN],head,tail,c[5];
bool vis[MAXN];
struct edge{
      int y,next,v;
}e[MAXN];
namespace solution{
      int gcd(int a,int b){return b==0?a:gcd(b,a%b);}
      inline void insert(int x,int y,int v){e[++len].next=LINK[x];LINK[x]=len;e[len].y=y;e[len].v=v;}
      void init(){
            N=read();
            up(i,1,N-1){
                  int x=read(),y=read(),v=read();
                  insert(x,y,v);
                  insert(y,x,v);
            }
      }
      void getroot(int node,int fa){
            siz[node]=1;ms[node]=0;
            for(int i=LINK[node];i;i=e[i].next)
                  if(!vis[e[i].y]&&e[i].y!=fa){
                        getroot(e[i].y,node);
                        siz[node]+=siz[e[i].y];
                        ms[node]=max(ms[node],siz[e[i].y]);
                  }
            ms[node]=max(ms[node],sum-siz[node]);
            if(ms[node]<ms[root])root=node;
      }
      void getdeep(int node,int fa){
            c[dis[node]]++;
            for(int i=LINK[node];i;i=e[i].next)
                  if(!vis[e[i].y]&&e[i].y!=fa){
                        dis[e[i].y]=(dis[node]+e[i].v)%3;
                        getdeep(e[i].y,node);
                  }
      }
      int col(int node,int di){
            c[0]=c[1]=c[2]=0;
            dis[node]=di%3;
            getdeep(node,0);
            return c[1]*c[2]*2+c[0]*c[0];

      }
      void work(int node){
            ans+=col(node,0);
            vis[node]=1;
            for(int i=LINK[node];i;i=e[i].next)
                  if(!vis[e[i].y]){
                        ans-=col(e[i].y,e[i].v);
                        sum=siz[e[i].y];root=0;
                        getroot(e[i].y,node);
                        work(root);
                  }
      }
      void slove(){
            memset(vis,0,sizeof(vis));
            ms[0]=oo;sum=N;
            getroot(1,0);
            work(root);
      }
      void output(){
            int d=gcd(ans,N*N);
            printf("%d/%d\n",(ans)/d,N*N/d);
      }
}
int main(){
      //freopen("input.in","r",stdin);
      using namespace solution;
      init();
      slove();
      output();
      return 0;
}

 

点分治

标签:

原文地址:http://www.cnblogs.com/Cydiater/p/5792756.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!