bzoj3451 Normal

题意:点分治每次随机选重心,求期望复杂度。

发现一次点分治的复杂度就是点分树上每个节点的子树大小之和。(并没有发现......)

这个

注意这个写法有问题,随便来个菊花图就是n2了。

每一层点分治的时候,时间复杂度决不能与上一层大小挂钩。

  1 /**************************************************************
  2     Problem: 3451
  3     Language: C++
  4     Result: Accepted
  5     Time:5548 ms
  6     Memory:8548 kb
  7 ****************************************************************/
  8  
  9 #include <cstdio>
 10 #include <algorithm>
 11 #include <cstring>
 12 #include <cmath>
 13  
 14 typedef long long LL;
 15 typedef long double LD;
 16 const LD pi = 3.1415926535897932384626;
 17 const int N = 30010, INF = 0x3f3f3f3f;
 18  
 19 inline void read(int &x) {
 20     x = 0;
 21     char c = getchar();
 22     while(c < '0' || c > '9') {
 23         c = getchar();
 24     }
 25     while(c >= '0' && c <= '9') {
 26         x = (x << 3) + (x << 1) + c - 48;
 27         c = getchar();
 28     }
 29     return;
 30 }
 31  
 32 struct cp {
 33     LD x, y;
 34     cp(LD X = 0, LD Y = 0) {
 35         x = X;
 36         y = Y;
 37     }
 38     inline cp operator +(const cp &w) const {
 39         return cp(x + w.x, y + w.y);
 40     }
 41     inline cp operator -(const cp &w) const {
 42         return cp(x - w.x, y - w.y);
 43     }
 44     inline cp operator *(const cp &w) const {
 45         return cp(x * w.x - y * w.y, x * w.y + y * w.x);
 46     }
 47 }a[N * 4], b[N * 4];
 48  
 49 struct Edge {
 50     int nex, v;
 51 }edge[N << 1]; int tp;
 52  
 53 int r[N * 4], n, e[N], small, root, d[N], bin[N], cnt[N], _n, siz[N];
 54 bool del[N];
 55  
 56 inline void add(int x, int y) {
 57     tp++;
 58     edge[tp].v = y;
 59     edge[tp].nex = e[x];
 60     e[x] = tp;
 61     return;
 62 }
 63  
 64 inline void FFT(cp *a, int n, int f) {
 65     for(register int i = 0; i < n; i++) {
 66         if(i < r[i]) {
 67             std::swap(a[i], a[r[i]]);
 68         }
 69     }
 70     for(register int len = 1; len < n; len <<= 1) {
 71         cp Wn(cos(pi / len), f * sin(pi / len));
 72         for(register int i = 0; i < n; i += (len << 1)) {
 73             cp w(1, 0);
 74             for(register int j = 0; j < len; j++) {
 75                 cp t = a[i + len + j] * w;
 76                 a[i + len + j] = a[i + j] - t;
 77                 a[i + j] = a[i + j] + t;
 78                 w = w * Wn;
 79             }
 80         }
 81     }
 82     if(f == -1) {
 83         for(register int i = 0; i <= n; i++) {
 84             a[i].x /= n;
 85         }
 86     }
 87     return;
 88 }
 89  
 90 inline void cal(int n, int f) {
 91     /*printf("cal \n");
 92     for(int i = 0; i <= n; i++) {
 93         printf("%d ", bin[i]);
 94     }
 95     printf("\n");*/
 96     int lm = 1, len = 2;
 97     while(len <= n * 2) {
 98         len <<= 1;
 99         lm++;
100     }
101     for(register int i = 0; i <= len; i++) {
102         r[i] = (r[i >> 1] >> 1) | ((i & 1) << (lm - 1));
103     }
104     for(register int i = 0; i <= n; i++) {
105         a[i] = cp(bin[i], 0);
106     }
107     for(register int i = n + 1; i <= len; i++) {
108         a[i] = cp(0, 0);
109     }
110     FFT(a, len, 1);
111     for(register int i = 0; i <= len; i++) {
112         a[i] = a[i] * a[i];
113     }
114     FFT(a, len, -1);
115     /*for(int i = 0; i <= n + n; i++) {
116         printf("%d ", (int)(a[i].x + 0.5));
117     }
118     printf("\n");*/
119     for(register int i = 0; i <= len; i++) {
120         cnt[i] += f * (int)(a[i].x + 0.5);
121     }
122     return;
123 }
124  
125 void get_root(int x, int f) {
126     bin[d[x]]++;
127     siz[x] = 1;
128     int large = -1;
129     for(int i = e[x]; i; i = edge[i].nex) {
130         int y = edge[i].v;
131         if(y == f || del[y]) {
132             continue;
133         }
134         get_root(y, x);
135         siz[x] += siz[y];
136         large = std::max(large, siz[y]);
137     }
138     if(small > std::max(large, _n - siz[x])) {
139         small = std::max(large, _n - siz[x]);
140         root = x;
141     }
142     return;
143 }
144  
145 void DFS(int x, int f) {
146     d[x] = d[f] + 1;
147     bin[d[x]]++;
148     siz[x] = 1;
149     for(int i = e[x]; i; i = edge[i].nex) {
150         int y = edge[i].v;
151         if(y == f || del[y]) {
152             continue;
153         }
154         DFS(y, x);
155         siz[x] += siz[y];
156     }
157     return;
158 }
159  
160 void div(int x, int f, int last_n) {
161     if(f) {
162         memset(bin, 0, sizeof(int) * (last_n + 1));
163     }
164     small = INF;
165     get_root(x, 0);
166     if(f) {
167         cal(last_n, -1);
168     }
169     x = root;
170     memset(bin, 0, sizeof(int) * (_n + 1));
171     DFS(x, 0);
172     cal(_n, 1);
173     del[x] = 1;
174     for(int i = e[x]; i; i = edge[i].nex) {
175         int y = edge[i].v;
176         if(del[y]) {
177             continue;
178         }
179         _n = siz[y];
180         div(y, 1, siz[x]);
181     }
182     return;
183 }
184  
185 int main() {
186     d[0] = -1;
187     read(n);
188     for(register int i = 1, x, y; i < n; i++) {
189         read(x); read(y);
190         add(x + 1, y + 1); add(y + 1, x + 1);
191     }
192  
193     _n = n;
194     div(1, 0, n);
195     LD ans = 0;
196     /*for(int i = 0; i <= n; i++) {
197         printf("%d ", cnt[i]);
198     }
199     printf("\n");*/
200     for(register int i = 0; i < n; i++) {
201         ans += (LD)cnt[i] / (i + 1);
202     }
203     printf("%.4Lf\n", ans);
204     return 0;
205 }
AC代码

注意FFT里面j从0开始,到len。

posted @ 2019-02-21 18:29  huyufeifei  阅读(142)  评论(0编辑  收藏  举报
试着放一个广告栏(虽然没有一分钱广告费)

『Flyable Heart 応援中!』 HHG 高苗京铃 闪十PSS 双六 電動伝奇堂 章鱼罐头制作组 はきか 祝姬 星降夜