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

真--可并堆模板--BZOJ2333: [SCOI2011]棘手的操作

时间:2018-01-11 22:15:13      阅读:192      评论:0      收藏:0      [点我收藏+]

标签:space   get   修改   roo   getchar   char   gpo   play   根据   

n<=300000个点,开始是独立的,m<=300000个操作:

技术分享图片

方法一:单点修改、查询,区间修改、查询?等等等等这里修改是块修改不是连续的啊,那就让他连续呗!具体方法:离线后,每次连接两棵树u,v时,把v放到u树根节点的最后,使其dfs序最后,最后扫一次把每棵树dfs一下搞出这个序列,然后线段树操作即可。

怎么把v放到u的儿子最后???强制一下连边顺序!!根据你写的邻接表,决定过程中的边是要正连还是倒连以达到目标顺序。有点抽象,见代码。

没写。

方法二:真正“棘手的操作”--可并堆!!!

如果是散散的点再连起来,可并堆的期望深度是小小的,可以做标记下传的!!

大体的思路是,每个块一个堆,然后每个堆的根节点的值再搞一个堆,就可以回答所有询问。然后来看看怎么操作:

U:直接合并。

A1:单点加,那就相当于单点查,单点删,单点加。单点删和单点加详见技术分享图片

单点查的话就标记下传就行了。。

A2:块加,打标记。

A3:是来搞笑的吗,记个全局变量。

F1:单点查,同上。

F2,F3:来搞笑的。

总之,重点在于:两个堆同时操作。

这次复合数据结构题的整体构思比以前有进步,但!!可并堆和并查集的结合非常混乱,这题要再写。

技术分享图片
  1 #include<string.h>
  2 #include<stdlib.h>
  3 #include<stdio.h>
  4 #include<math.h>
  5 //#include<assert.h>
  6 #include<algorithm>
  7 //#include<iostream>
  8 using namespace std;
  9 
 10 int n,m;
 11 #define maxn 300011
 12 struct leftist
 13 {
 14     struct Node
 15     {
 16         int fa,ls,rs,v,dis,add;
 17     }a[maxn];
 18     leftist() {a[0].dis=-1;}
 19     void addsingle(int x,int v)
 20     {
 21         if (!x) return;
 22         (a[x].v+=v);
 23         a[x].add+=v;
 24     }
 25     void down(int x)
 26     {
 27         int &p=a[x].ls,&q=a[x].rs;
 28         if (a[x].add) {addsingle(p,a[x].add); addsingle(q,a[x].add); a[x].add=0;}
 29     }
 30     int sta[maxn];
 31     void download(int x)
 32     {
 33         int top=0;
 34         for (int i=x;i;i=a[i].fa) sta[++top]=i;
 35         for (;top;top--) down(sta[top]);
 36     }
 37     int merge(int x,int y)
 38     {
 39         if (!x || !y) return x^y;
 40         if (a[x].v<a[y].v) {int t=x; x=y; y=t;}
 41         down(x);
 42         a[x].rs=merge(a[x].rs,y);
 43         if (a[a[x].ls].dis<a[a[x].rs].dis) {int t=a[x].ls; a[x].ls=a[x].rs; a[x].rs=t;}
 44         a[x].dis=a[a[x].rs].dis+1;
 45         if (a[x].rs) a[a[x].rs].fa=x; if (a[x].ls) a[a[x].ls].fa=x;
 46         return x;
 47     }
 48     void Delete(int &root,int x)
 49     {
 50         int y=a[x].fa,w=(x==a[y].rs); x=merge(a[x].ls,a[x].rs); a[x].fa=y;
 51         if (!y) {root=x; return;}
 52         if (w) a[y].rs=x; else a[y].ls=x;
 53         if (a[a[y].ls].dis<a[a[y].rs].dis) {int t=a[y].ls; a[y].ls=a[y].rs; a[y].rs=t;}
 54         x=a[y].rs;
 55         while (y && a[y].dis!=a[x].dis+1)
 56         {
 57             a[y].dis=a[x].dis+1;
 58             x=y; y=a[y].fa;
 59             if (a[a[y].ls].dis<a[a[y].rs].dis) {int t=a[y].ls; a[y].ls=a[y].rs; a[y].rs=t;}
 60             x=a[y].rs;
 61         }
 62     }
 63     void push(int id,int &root,int val)
 64     {
 65         a[id].fa=a[id].ls=a[id].rs=a[id].dis=a[id].add=0; a[id].v=val;
 66         root=merge(root,id);
 67     }
 68     int top(int root) {return a[root].v;}
 69 }q,qtot;
 70 int root[maxn];
 71 int find(int x) {return x==root[x]?x:(root[x]=find(root[x]));}
 72 
 73 int main()
 74 {
 75     scanf("%d",&n);
 76     for (int i=1,x;i<=n;i++) scanf("%d",&x),q.push(i,root[i],x),qtot.push(i,root[0],x);
 77     scanf("%d",&m);
 78     char c;int x,y; int totadd=0;
 79     for (int i=1;i<=m;i++)
 80     {
 81         while ((c=getchar())!=U && c!=A && c!=F);
 82         if (c==U)
 83         {
 84             scanf("%d%d",&x,&y); x=find(x); y=find(y);
 85             if (x==y) continue;
 86             qtot.Delete(root[0],y); qtot.Delete(root[0],x);
 87             root[x]=root[y]=q.merge(x,y);
 88             x=root[x]; qtot.push(x,root[0],q.a[x].v);
 89         }
 90         else if (c==A)
 91         {
 92             c=getchar();
 93             if (c==1)
 94             {
 95                 scanf("%d%d",&x,&y); find(x);
 96                 qtot.Delete(root[0],root[x]);
 97                 q.download(x); int tmp=q.a[x].v;
 98                 q.Delete(root[x],x); int z=root[x];
 99                 if (z) root[z]=z,q.push(x,root[z],tmp+y),root[x]=root[z];
100                 else q.push(x,root[x],tmp+y);
101                 qtot.push(root[x],root[0],q.a[root[x]].v);
102             }
103             else if (c==2)
104             {
105                 scanf("%d%d",&x,&y); x=find(x); qtot.Delete(root[0],x);
106                 q.addsingle(x,y); qtot.push(x,root[0],q.a[x].v);
107             }
108             else if (c==3)
109             {
110                 scanf("%d",&x);
111                 totadd+=x;
112             }
113         }
114         else
115         {
116             c=getchar();
117             if (c==1)
118             {
119                 scanf("%d",&x);
120                 q.download(x);
121                 printf("%d\n",q.a[x].v+totadd);
122             }
123             else if (c==2)
124             {
125                 scanf("%d",&x); x=find(x);
126                 printf("%d\n",q.a[x].v+totadd);
127             }
128             else printf("%d\n",qtot.a[root[0]].v+totadd);
129         }
130     }
131     return 0;
132 }
View Code

 

真--可并堆模板--BZOJ2333: [SCOI2011]棘手的操作

标签:space   get   修改   roo   getchar   char   gpo   play   根据   

原文地址:https://www.cnblogs.com/Blue233333/p/8270329.html

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