zoukankan      html  css  js  c++  java
  • 题解 P3605 【[USACO17JAN]Promotion Counting晋升者计数】

    这道题开10倍左右一直MLE+RE,然后尝试着开了20倍就A了。。。窒息


    对于这道题目,我们考虑使用线段树合并来做。

    所谓线段树合并,就是把结构相同的线段树上的节点的信息合在一起,合并的方式比较类似左偏树什么的。


    我们对于每个节点用权值线段树查询大于它的子节点数量,然后把当前节点并到它的父亲上面去。

    对于此类型的题目我们通常使用动态开点的线段树(不然炸的没边)。

    时间复杂度应该是$O(nlogn)$


    AC代码如下:

    455ms 32824kb

     1 #include <bits/stdc++.h>
     2 
     3 using namespace std;
     4 
     5 namespace StandardIO {
     6 
     7     template<typename T> inline void read (T &x) {
     8         x=0;T f=1;char c=getchar();
     9         for(; c<'0'||c>'9'; c=getchar()) if(c=='-') f=-1;
    10         for(; c>='0'&&c<='9'; c=getchar()) x=x*10+c-'0';
    11         x*=f;
    12     }
    13     template<typename T>inline void write (T x) {
    14         if (x<0) putchar('-'),x*=-1;
    15         if (x>=10) write(x/10);
    16         putchar(x%10+'0');
    17     }
    18 
    19 }
    20 
    21 using namespace StandardIO;
    22 
    23 namespace Solve {
    24     
    25     const int N=100100;
    26     
    27     int n;
    28     int cnt;
    29     struct node {
    30         int id,v;
    31         inline bool operator < (const node &x) const {
    32             return v<x.v;
    33         }
    34     }p[N];
    35     vector<int>graph[N];
    36     int tree_node;
    37     int val[N],tree[(int)(N*20)],ls[(int)(N*20)],rs[(int)(N*20)],root[N],ans[N];
    38     
    39     void build (int l,int r,int v,int &root) {
    40         if (!root) root=++tree_node;
    41         tree[root]++;
    42         if (l==r) return;
    43         int mid=(l+r)>>1;
    44         if (v<=mid) build(l,mid,v,ls[root]);
    45         else build(mid+1,r,v,rs[root]);
    46     }
    47     int query (int l,int r,int v,int root) {
    48         if (!root) return 0;
    49         if (v<=l) return tree[root];
    50         int mid=(l+r)>>1;
    51         if (v<=mid) return query(l,mid,v,ls[root])+query(mid+1,r,v,rs[root]);
    52         return query(mid+1,r,v,rs[root]);
    53     }
    54     int merge (int x,int y) {
    55         if (!x||!y) return x+y;
    56         int root=++tree_node;
    57         tree[root]=tree[x]+tree[y];
    58         ls[root]=merge(ls[x],ls[y]);
    59         rs[root]=merge(rs[x],rs[y]);
    60         return root;
    61     }
    62     void dfs (int now) {
    63         for (register int i=0; i<graph[now].size(); ++i) {
    64             int to=graph[now][i];
    65             dfs(to);
    66             root[now]=merge(root[now],root[to]);
    67         }
    68         ans[now]=query(1,cnt,val[now]+1,root[now]);
    69         build(1,cnt,val[now],root[now]);
    70     }
    71     
    72     inline void solve () {
    73         read(n);
    74         for (register int i=1; i<=n; ++i) {
    75             read(p[i].v),p[i].id=i;
    76         }
    77         sort(p+1,p+n+1);
    78         for (register int i=1; i<=n; ++i) {
    79             if (p[i].v!=p[i-1].v) val[p[i].id]=++cnt;
    80             else val[p[i].id]=cnt;
    81         }
    82         for (register int i=2; i<=n; ++i) {
    83             int x;read(x);
    84             graph[x].push_back(i);
    85         }
    86         dfs(1);
    87         for (register int i=1; i<=n; ++i) {
    88             write(ans[i]),putchar('
    ');
    89         }
    90     }
    91 }
    92 
    93 using namespace Solve;
    94 
    95 int main () {
    96     solve();
    97 }
  • 相关阅读:
    DB2去重的几种方法
    split命令:文件切割
    DB2中横表纵表互换
    做一个思想的码农
    access应用分享
    回顾2015年
    笑看互联网金融
    Razor语法
    数据库操作(二)
    SQL Server数据库简介(一)
  • 原文地址:https://www.cnblogs.com/ilverene/p/9841094.html
Copyright © 2011-2022 走看看