BZOJ 3648 Bedroom Management

【answer】

  GDOI2016 Day2T3

  If the given data is a tree, then you can just divide and conquer directly, and use a tree array to maintain the number of numbers greater than x. If it is a base ring tree, we first break an edge on the ring, and then run the point divide and conquer; plus the number of solutions passing through this edge, in fact, starting from an endpoint of the broken edge, put The loop is traversed once, and the way to update the contribution is similar to that in the point-and-conquer process, see Note 2333 for details.

  

 1 #include<cstdio>
 2 #include<algorithm>
 3 #define rg register
 4 #define N 100010
 5 #define LL long long
 6 using namespace std;
 7 int n,m,k,tot,cnt,top,cir,root;
 8 int last[N],dep[N],bit[N<<1],siz[N],mxsiz[N],st[N],c[N];
 9 bool cut[N<<1],v[N];
10 LL ans=0;
11 struct edge{
12     int to,pre,dis;
13 }e[N<<1];
14 inline int read(){
15     int k=0,f=1; char c=getchar();
16     while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar();
17     while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar();
18     return k*f;
19 }
20 inline void add(int x,int y){for(;x>0;x-=(x&-x))bit[x]+=y;}
21 inline int query(int x){
22     if(x<1) x=1; int ret=0;
23     for(;x<=n+cir;x+=(x&-x)) ret+=bit[x]; return ret;
24 }
25 void findcircle(int x,int fa){
26     if(cir) return;
27     if(v[x]){
28         c[cir=1]=x;
29         for(rg int i=top;st[i]!=x;c[++cir]=st[i--]);
30     }
31     v[x]=1; st[++top]=x;
32     for(rg int i=last[x],to;i;i=e[i].pre)
33         if((to=e[i].to)!=fa) findcircle(to,x);
34     v[x]=0; top--;
35 }
36 void getroot(int x,int fa){
37     siz[x]=1; mxsiz[x]=0;
38     for(rg int i=last[x],to;i;i=e[i].pre)if(!v[to=e[i].to]&&to!=fa&&!cut[i]){
39         getroot(to,x); siz[x]+=siz[to];
40         mxsiz[x]=max(mxsiz[x],siz[to]);
41     }
42     mxsiz[x]=max(mxsiz[x],cnt-mxsiz[x]);
43     if(!root||mxsiz[x]<mxsiz[root]) root=x;
44 }
45 void getdep(int x,int fa,int d){
46     st[++top]=d;
47     for(rg int i=last[x],to;i;i=e[i].pre)
48     if(!v[to=e[i].to]&&to!=fa&&!cut[i]) getdep(to,x,d+1);
49 }
50 void dfs(int x){
51     int l=0; v[x]=1;
52     for(rg int i=last[x],to;i;i=e[i].pre)
53     if(!v[to=e[i].to]&&!cut[i]){
54         l=top+1; getdep(to,x,1);
55         for(rg int j=l;j<=top;j++) ans+=query(k-st[j]-1);
56         for(rg int j=l;j<=top;j++) add(st[j],1);
57     }
58     ans+=query(k-1);
59     while(top) add(st[top--],-1);
60     for(rg int i=last[x],to;i;i=e[i].pre)
61     if(!v[to=e[i].to]&&!cut[i]&&siz[to]>=k){
62         cnt=siz[to]; root=0; getroot(to,x); dfs(root);
63     }
64 }
65 int main(){
66     n=read(); m=read(); k=read();
67     for(rg int i=1;i<=m;i++){
68         int u=read(),v=read();
69         e[++tot]=(edge){v,last[u]}; last[u]=tot;
70         e[++tot]=(edge){u,last[v]}; last[v]=tot;
71     }
72     if(m<n){
73         cnt=n; root=0; getroot(1,0); dfs(root);
74     }
75     else{
76         findcircle(1,0);
77         for(rg int i=last[c[1]],to;i;i=e[i].pre)if((to=e[i].to)==c[cir]){
78             cut[i]=1; break;
79         }
80         for(rg int i=last[c[cir]],to;i;i=e[i].pre)if((to=e[i].to)==c[1]){
81             cut[i]=1; break;
82         }
83         top=0; cnt=n; root=0; 
84         getroot(1,0); dfs(root);
85         top=0;
86         for(rg int i=1;i<=n;i++)v[i]=0;
87         for(rg int i=1;i<=cir+n;i++) bit[i]=0;
88         for(rg int i=1;i<=cir;i++) v[c[i]]=1;
89         for(rg int i=1;i<=cir;i++ ){
 90              v[c[i]]= 0 ;
 91              getdep(c[i], 0 , 0 );
 92              v[c[i]]= 1 ;
 93              for (rg int j = 1 ;j<=top;j++)ans+=query(k-(cir-i+ 1 )-st[j]); // cir-i+1 is the distance from one circle to the starting point on the ring 
94              while (top ) add(st[top--]+i, 1 ); // +i is the distance to the start of the ring 
95          }
 96      }
 97      printf( " %lld\n " ,ans);
98     return 0;
99 }
View Code

 

  

  

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324688632&siteId=291194637