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

P3521 [POI2011]ROT-Tree Rotations

时间:2019-02-13 20:51:12      阅读:143      评论:0      收藏:0      [点我收藏+]

标签:线段   ref   size   ota   超过   证明   merge   long   gif   

P3521 [POI2011]ROT-Tree Rotations

  本题可以通过合并数据结构解决。

  权值线段树合并的时间复杂度为O(nlogn)。

证明:

   • n个节点相互独立。

   • 考虑合并节点的意义:两棵线段树在当前区间内都有值且新的树在当前区间的值相对原来两棵树的值都增加了。

   • 说明对于一个线段树区间,merge时访问到它的次数不会超过该区间的长度大小次。

   • 那么显然总访问次数的上限为 nlogn。

 

技术图片
 1 #include<bits/stdc++.h>
 2 #define ll long long
 3 using namespace std;
 4 int n,root,now,cnt;
 5 ll a,b,ans;
 6 int sum[4000050];
 7 int son[4000050][2];
 8 void calc_add(int &u,int l,int r)
 9 {
10     u=++cnt;    ++sum[u];
11     if(l==r)    return ;
12     int mid=(l+r)>>1;
13     if(now<=mid)    calc_add(son[u][0],l,mid);
14     else            calc_add(son[u][1],mid+1,r);
15 }
16 void merge(int &u,int v)
17 {
18     if(!u||!v)
19     {
20         u=u|v;
21         return ;
22     }
23     sum[u]+=sum[v];
24     a+=(ll)sum[son[u][0]]*sum[son[v][1]];
25     b+=(ll)sum[son[u][1]]*sum[son[v][0]];
26     merge(son[u][0],son[v][0]);
27     merge(son[u][1],son[v][1]);
28 }
29 void dfs(int &u)
30 {
31     scanf("%d",&now);
32     int ls,rs;
33     if(!now)
34     {
35         dfs(ls=0);    dfs(rs=0);
36         a=b=0;    u=ls;
37         merge(u,rs);
38         ans+=min(a,b);
39     }
40     else
41         calc_add(u,1,n);
42 }
43 int main()
44 {
45     scanf("%d",&n);
46     dfs(root);
47     printf("%lld",ans);
48     return 0;
49 }
View Code

 

P3521 [POI2011]ROT-Tree Rotations

标签:线段   ref   size   ota   超过   证明   merge   long   gif   

原文地址:https://www.cnblogs.com/wyher/p/10371530.html

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