• 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 
    ");
     92     for(int i = 0; i <= n; i++) {
     93         printf("%d ", bin[i]);
     94     }
     95     printf("
    ");*/
     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("
    ");*/
    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("
    ");*/
    200     for(register int i = 0; i < n; i++) {
    201         ans += (LD)cnt[i] / (i + 1);
    202     }
    203     printf("%.4Lf
    ", ans);
    204     return 0;
    205 }
    AC代码

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

  • 相关阅读:
    [第二届构建之法论坛] 预培训文档(Java版)
    避免走进熟人社交的误区——给新手助教的几个建议
    BugPhobia发布篇章:Beta版本学霸在线系统正式发布
    BugPhobia回顾篇章:团队Beta 阶段工作分析
    BugPhobia终章篇章:学霸在线系统Beta阶段展示
    BugPhobia发布篇章:学霸在线系统测试报告
    BugPhobia开发终结篇章:Beta阶段第XI次Scrum Meeting
    BugPhobia开发篇章:Beta阶段第X次Scrum Meeting
    BugPhobia开发篇章:Beta阶段第IX次Scrum Meeting
    BugPhobia休息篇章:Beta阶段第IX次Scrum Meeting前奏
  • 原文地址:https://www.cnblogs.com/huyufeifei/p/10414474.html
Copyright © 2020-2023  润新知