【BZOJ 2333 】[SCOI2011]棘手的操作(离线+线段树|可并堆-左偏树)

 

2333: [SCOI2011]棘手的操作

Description

N个节点,标号从1N,这N个节点一开始相互不连通。第i个节点的初始权值为a[i],接下来有如下一些操作:

U x y: 加一条边,连接第x个节点和第y个节点

A1 x v: 将第x个节点的权值增加v

A2 x v: 将第x个节点所在的连通块的所有节点的权值都增加v

A3 v: 将所有节点的权值都增加v

F1 x: 输出第x个节点当前的权值

F2 x: 输出第x个节点所在的连通块中,权值最大的节点的权值

F3: 输出所有节点中,权值最大的节点的权值

Input

输入的第一行是一个整数N,代表节点个数。

接下来一行输入N个整数,a[1], a[2], …, a[N],代表N个节点的初始权值。

再下一行输入一个整数Q,代表接下来的操作数。

最后输入Q行,每行的格式如题目描述所示。

Output

对于操作F1, F2, F3,输出对应的结果,每个结果占一行。

Sample Input

3

0 0 0

8

A1 3 -20

A1 2 20

U 1 3

A2 1 10

F1 3

F2 3

A3 -10

F3

Sample Output


-10

10

10

HINT



 对于30%的数据,保证 N<=100,Q<=10000


对于80%的数据,保证 N<=100000,Q<=100000


对于100%的数据,保证 N<=300000,Q<=300000


对于所有的数据,保证输入合法,并且 -1000<=v, a[1], a[2], …, a[N]<=1000

 

 

【分析】

  这题不知道算不算有想法?

  还是看了题解,其实也不是很难想,可能是我做的题太少了。 【不会可并堆ORZ】

  然后这一题可以离线,因为add的是联通块,而且一旦union也就不会分开了,所以就会希望可以把点重新编号,联通块的编号在一个区间里(因为可以离线)。

  所以,先预处理,建一棵合并过程的树,用并查集维护,即连接两个联通块时新建一个点,左右孩子连两个连通块的fa,用dfs序,进行查询,修改。【orz奥爷爷

 

  1 #include
  2 #include
  3 #include
  4 #include
  5 #include
  6 #include
  7 #include
  8 using namespace std;
  9 #define Maxn 300010
 10 
 11 int son[2*Maxn][2];
 12 int a[Maxn],fa[Maxn*2]/*,f[Maxn*2]*/,tot;
 13 char s[10];
 14 
 15 int mymax(int x,int y) {return x>y?x:y;}
 16 
 17 struct hp
 18 {
 19     int op,x,y,id;
 20 }q[Maxn];int ql;
 21 
 22 int ffa(int x)
 23 {
 24     if(x!=fa[x]) fa[x]=ffa(fa[x]);
 25     return fa[x];
 26 }
 27 
 28 int n;
 29 void init()
 30 {
 31     scanf("%d",&n);
 32     for(int i=1;i<=n;i++) scanf("%d",&a[i]);
 33     for(int i=1;i<=n;i++) fa[i]=i;tot=n;
 34     int m;
 35     scanf("%d",&m);
 36     ql=0;
 37     memset(son,0,sizeof(son));
 38     for(int i=1;i<=m;i++)
 39     {
 40         scanf("%s",s);
 41         int x,y;
 42         if(s[0]=='U')
 43         {
 44             scanf("%d%d",&x,&y);
 45             if(ffa(x)==ffa(y)) continue;
 46             tot++;
 47             son[tot][0]=ffa(x);son[tot][1]=ffa(y);
 48             fa[tot]=tot;
 49             fa[ffa(x)]=tot;fa[ffa(y)]=tot;
 50         }
 51         else if(s[0]=='A'&&s[1]=='1')
 52         {
 53             scanf("%d%d",&x,&y);
 54             q[++ql].op=0;q[ql].x=x;q[ql].y=y;
 55         }
 56         else if(s[0]=='A'&&s[1]=='2')
 57         {
 58             scanf("%d%d",&x,&y);
 59             q[++ql].op=1;q[ql].x=x;q[ql].y=y;q[ql].id=ffa(x);
 60         }
 61         else if(s[0]=='A')
 62         {
 63             scanf("%d",&x);
 64             q[++ql].op=2;q[ql].x=x;
 65             
 66         }
 67         else if(s[0]=='F'&&s[1]=='1')
 68         {
 69             scanf("%d",&x);
 70             q[++ql].op=3;q[ql].x=x;
 71         }
 72         else if(s[0]=='F'&&s[1]=='2')
 73         {
 74             scanf("%d",&x);
 75             q[++ql].op=4;q[ql].x=x;q[ql].id=ffa(x);
 76         }
 77         else
 78         {
 79             q[++ql].op=5;
 80         }
 81     }
 82 }
 83 
 84 int cnt,dfn[Maxn],lf[2*Maxn],rt[2*Maxn];
 85 void dfs(int x)
 86 {
 87     if(x<=n)
 88     {
 89         dfn[x]=++cnt;
 90         lf[x]=rt[x]=dfn[x];
 91         return;
 92     }
 93     dfs(son[x][0]);lf[x]=lf[son[x][0]];
 94     dfs(son[x][1]);rt[x]=rt[son[x][1]];
 95 }
 96 
 97 struct node
 98 {
 99     int l,r,lc,rc,mx;
100     int lazy;
101 }t[Maxn*4];int len;
102 
103 void upd(int x)
104 {
105     if(t[x].lazy==0) return;
106     t[x].mx+=t[x].lazy;
107     if(t[x].l!=t[x].r)
108     {
109         int lc=t[x].lc,rc=t[x].rc;
110         t[lc].lazy+=t[x].lazy;
111         t[rc].lazy+=t[x].lazy;
112     }
113     t[x].lazy=0;
114 }
115 
116 int build(int l,int r)
117 {
118     int x=++len;
119     t[x].l=l;t[x].r=r;t[x].mx=0;
120     t[x].lazy=0;
121     if(l!=r)
122     {
123         int mid=(l+r)>>1;
124         t[x].lc=build(l,mid);
125         t[x].rc=build(mid+1,r);
126     }
127     else t[x].lc=t[x].rc=0;
128     return x;
129 }
130 
131 void add(int x,int l,int r,int y)
132 {
133     if(y==0) return;
134     if(t[x].l==l&&t[x].r==r)
135     {
136         t[x].lazy+=y;
137         return;
138     }
139     upd(x);
140     int mid=(t[x].l+t[x].r)>>1;
141     if(r<=mid) add(t[x].lc,l,r,y);
142     else if(l>mid) add(t[x].rc,l,r,y);
143     else
144     {
145         add(t[x].lc,l,mid,y);
146         add(t[x].rc,mid+1,r,y);
147     }
148     int lc=t[x].lc,rc=t[x].rc;
149     upd(lc);upd(rc);
150     t[x].mx=mymax(t[lc].mx,t[rc].mx);
151 }
152 
153 int query(int x,int l,int r)
154 {
155     upd(x);
156     if(t[x].l==l&&t[x].r==r) return t[x].mx;
157     int mid=(t[x].l+t[x].r)>>1;
158     if(r<=mid) return query(t[x].lc,l,r);
159     else if(l>mid) return query(t[x].rc,l,r);
160     else return mymax(query(t[x].lc,l,mid),query(t[x].rc,mid+1,r));
161 }
162 
163 int main()
164 {
165     init();
166     len=0;
167     build(1,tot);
168     cnt=0;int ad=0;
169     for(int i=1;i<=tot;i++) if(ffa(i)==i)
170     {
171         dfs(i);
172     }
173     for(int i=1;i<=n;i++) add(1,dfn[i],dfn[i],a[i]);
174     for(int i=1;i<=ql;i++)
175     {
176         if(q[i].op==0)
177         {
178             // printf("add %d %d %d\n",dfn[q[i].x],dfn[q[i].x],q[i].y);
179             add(1,dfn[q[i].x],dfn[q[i].x],q[i].y);
180         }
181         else if(q[i].op==1)
182         {
183             // printf("add %d %d %d\n",lf[q[i].id],rt[q[i].id],q[i].y);
184             add(1,lf[q[i].id],rt[q[i].id],q[i].y);
185         }
186         else if(q[i].op==2)
187         {
188             ad+=q[i].x;
189         }
190         else if(q[i].op==3)
191         {
192             // printf("ask %d %d\n",dfn[q[i].x],dfn[q[i].x]);
193             int now=query(1,dfn[q[i].x],dfn[q[i].x]);
194             printf("%d\n",now+ad);
195         }
196         else if(q[i].op==4)
197         {
198             // printf("ask %d %d\n",lf[q[i].id],rt[q[i].id]);
199             int now=query(1,lf[q[i].id],rt[q[i].id]);
200             printf("%d\n",now+ad);
201         }
202         else if(q[i].op==5)
203         {
204             int now=query(1,1,cnt);
205             printf("%d\n",now+ad);
206         }
207     }
208     return 0;
209 }
View Code

 

2016-11-10 09:49:34

 


 

学了可并堆我回来更新啦哈哈哈哈【傻。。

【感觉这个题号在嘲笑我><】

左偏树,还要带lazy标记,还要加一个set,呵呵呵,因为看不懂别人的,所以自己YYYYY,所以就乱搞了一整天+很多呆滞的moment。。

细节真心超多,

我搞了个rt(用并查集维护),还有一个fa(左偏树中直属父亲)。

fa,从下往上找,然后从上往下pushdown那里好像有点慢,不过我看黄学长这里也是这样的。【表示左偏树做法比离线慢呐~~

A1操作先删点,再加点,细节很多!!!【因为我乱搞呵呵呵呵
= =或许应该看这个题解:http://blog.csdn.net/charlie_pyc/article/details/20830305

 

  1 #include
  2 #include
  3 #include
  4 #include
  5 #include
  6 #include<set>
  7 using namespace std;
  8 #define Maxn 300010
  9 #define INF 0x7fffffff
 10 
 11 int mymax(int x,int y) {return x>y?x:y;}
 12 
 13 int a[Maxn],all=0;
 14 int n,q,cnt;
 15 char s[100];
 16 
 17 multiset<int > ss;
 18 
 19 struct node
 20 {
 21     int x,lc,rc,dis,fa,rt;
 22     int lazy;
 23 }t[Maxn];
 24 
 25 void upd(int x)
 26 {
 27     t[x].lc=t[x].rc=0;
 28     t[x].dis=0;t[x].lazy=0;
 29     t[x].fa=0;
 30 }
 31 
 32 void era(int x)
 33 {
 34     multiset<int>:: iterator it;
 35     it=ss.find(x);
 36     ss.erase(it);
 37 }
 38 
 39 
 40 int v[Maxn];
 41 struct Ltree
 42 {
 43     int rtt(int x)
 44     {
 45         if(t[x].rt!=x) t[x].rt=rtt(t[x].rt);
 46         return t[x].rt;
 47     }
 48     void pushdown(int x)
 49     {
 50         if(t[x].lc) t[t[x].lc].lazy+=t[x].lazy;
 51         if(t[x].rc) t[t[x].rc].lazy+=t[x].lazy;
 52         t[x].x+=t[x].lazy;
 53         t[x].lazy=0;
 54     }
 55     int merge(int x,int y)
 56     {
 57         if(x==0||y==0) return x+y;
 58         pushdown(x);pushdown(y);
 59         if(t[x].x<t[y].x) swap(x,y);
 60         t[x].rc=merge(t[x].rc,y);
 61         if(t[x].rc) t[t[x].rc].fa=x;
 62         if(t[t[x].lc].dis<t[t[x].rc].dis) swap(t[x].lc,t[x].rc);
 63         t[x].dis=t[t[x].rc].dis+1;
 64         return x;
 65     }
 66     void sol(int x)
 67     {
 68         v[0]=0;
 69         while(x) v[++v[0]]=x,x=t[x].fa;
 70         while(v[0]) pushdown(v[v[0]--]);
 71     }
 72     int add(int x,int y)
 73     {
 74         int xx=rtt(x);
 75         pushdown(xx);era(t[xx].x);sol(x);
 76         int nw=merge(t[x].lc,t[x].rc);
 77         if(t[x].fa)
 78         {
 79             if(t[t[x].fa].lc==x) t[t[x].fa].lc=nw;
 80             else t[t[x].fa].rc=nw;
 81         }
 82         if(nw)
 83         {
 84             t[nw].fa=t[x].fa;
 85         }
 86         t[x].x+=y;upd(x);
 87         if(x!=xx) nw=merge(x,xx);
 88         else nw=merge(x,nw);
 89         
 90         t[x].rt=t[xx].rt=t[nw].rt=nw;
 91         pushdown(nw);
 92         ss.insert(t[nw].x);
 93     }
 94 }heap;
 95 
 96 int main()
 97 {
 98     scanf("%d",&n);
 99     t[0].dis=-1;
100     for(int i=1;i<=n;i++) scanf("%d",&a[i]);
101     for(int i=1;i<=n;i++) upd(i),t[i].x=a[i],t[i].fa=0,t[i].rt=i;
102     ss.clear();
103     for(int i=1;i<=n;i++) ss.insert(a[i]);
104     
105     scanf("%d",&q);
106     for(int i=1;i<=q;i++)
107     {
108         scanf("%s",s);
109         int x,y;
110         if(s[0]=='U')
111         {
112             scanf("%d%d",&x,&y);
113             int xx=heap.rtt(x),yy=heap.rtt(y);
114             if(xx==yy) continue;
115             heap.pushdown(xx);era(t[xx].x);
116             heap.pushdown(yy);era(t[yy].x);
117             int nw=heap.merge(xx,yy);
118             t[xx].rt=t[yy].rt=nw;
119             heap.pushdown(nw);ss.insert(t[nw].x);
120         }
121         else if(s[0]=='A')
122         {
123             if(s[1]=='1')
124             {
125                 scanf("%d%d",&x,&y);
126                 heap.add(x,y);
127             }
128             else if(s[1]=='2')
129             {
130                 scanf("%d%d",&x,&y);
131                 int xx=heap.rtt(x);
132                                                 heap.pushdown(xx);
133                 era(t[xx].x);
134                 t[xx].lazy+=y;
135                                                 heap.pushdown(xx);
136                 ss.insert(t[xx].x);
137             }
138             else
139             {
140                 scanf("%d",&x);
141                 all+=x;
142             }
143         }
144         else 
145         {
146             if(s[1]=='1')
147             {
148                 scanf("%d",&x);
149                 heap.sol(x);
150                 heap.pushdown(x);
151                 printf("%d\n",t[x].x+all);
152             }
153             else if(s[1]=='2')
154             {
155                 scanf("%d",&x);
156                 int xx=heap.rtt(x);
157                 heap.pushdown(xx);
158                 printf("%d\n",t[xx].x+all);
159             }
160             else
161             {
162                 printf("%d\n",*(--ss.end())+all);
163             }
164         }
165     }
166     return 0;
167 }
View Code

2017-01-20 17:05:47

 


 

在后面再写一题:(因为没A就插在AC的题目后面吧)

HDU5454

【题意】

n*n的矩阵,每次对连续的一段对角线全部加1,每次询问一个子矩阵的和(n<=200000)

【分析】

跟那道矩阵旋转的线段树维护有点像。要对矩阵的对角线以及旋转有很深的理解才行啊。。。

对于左斜线来说,加的值都是一样的,右斜线也是。所以可以分开维护。

一个矩形就可以分成一个平行四边形和两个三角形咯,平行四边形那里对角线长度相等,可以求和,三角形的话,对角线长度是递增的,所以可以维护类似a[i]*i的前缀和。。、

 

 

超难打ORZ .....

放个还没有AC的代码:

  1 #include
  2 #include
  3 #include
  4 #include
  5 #include
  6 #include
  7 using namespace std;
  8 #define INF 0xfffffff
  9 #define Maxn 200010
 10 
 11 struct node
 12 {
 13     int l,r,lc,rc,f[2],f1[2],f2[2];
 14     int lazy[2];
 15 }t[2*Maxn];int len;
 16 
 17 int n,m;
 18 int myabs(int x) {return x>0?x:-x;}
 19 int mymin(int x,int y) {return xx:y;}
 20 int mymax(int x,int y) {return x>y?x:y;}
 21 
 22 int build(int l,int r)
 23 {
 24     int x=++len;
 25     t[x].l=l;t[x].r=r;
 26     t[x].f[0]=t[x].f[1]=t[x].f1[0]=t[x].f1[1]=t[x].f2[0]=t[x].f2[1]=0;
 27     t[x].lazy[0]=t[x].lazy[1]=0;
 28     if(l!=r)
 29     {
 30         int mid=(l+r)>>1;
 31         t[x].lc=build(l,mid);
 32         t[x].rc=build(mid+1,r);
 33     }
 34     else t[x].lc=t[x].rc=0;
 35     return x;
 36 }
 37 
 38 int gsum(int l,int r)
 39 {
 40     return (l+r)*(r-l+1)/2;
 41 }
 42 
 43 void upd(int x,int p)
 44 {
 45     if(t[x].lazy[p]==0) return;
 46     int lc=t[x].lc,rc=t[x].rc;
 47     t[x].f[p]+=t[x].lazy[p]*(t[x].r-t[x].l+1);
 48     t[x].f1[p]+=t[x].lazy[p]*gsum(t[x].l,t[x].r);
 49     t[x].f2[p]+=t[x].lazy[p]*gsum(2*n-t[x].r,2*n-t[x].l);
 50     t[lc].lazy[p]+=t[x].lazy[p];t[rc].lazy[p]+=t[x].lazy[p];
 51     t[x].lazy[p]=0;
 52     return;
 53 }
 54 
 55 void change(int x,int l,int r,int p)
 56 {
 57     if(t[x].l==l&&t[x].r==r)
 58     {
 59         t[x].lazy[p]++;
 60         return;
 61     }
 62     upd(x,p);
 63     int mid=(t[x].l+t[x].r)>>1;
 64     if(r<=mid) change(t[x].lc,l,r,p);
 65     else if(l>mid) change(t[x].rc,l,r,p);
 66     else
 67     {
 68         change(t[x].lc,l,mid,p);
 69         change(t[x].rc,mid+1,r,p);
 70     }
 71     int lc=t[x].lc,rc=t[x].rc;
 72     upd(lc,p);
 73     upd(rc,p);
 74     t[x].f[p]=t[lc].f[p]+t[rc].f[p];
 75     t[x].f1[p]=t[lc].f1[p]+t[rc].f1[p];
 76     t[x].f2[p]=t[lc].f2[p]+t[rc].f2[p];
 77 }
 78 
 79 int query(int x,int l,int r,int p,int op)
 80 {
 81     int tt;
 82     if(l>r) tt=l,l=r,r=tt;
 83     if(r>2*n-1) r=2*n-1;
 84     if(l<1) l=1;
 85     upd(x,p);
 86     if(t[x].l==l&&t[x].r==r)
 87     {
 88         if(op==0) return t[x].f1[p];
 89         else if(op==1) return t[x].f2[p];
 90         else return t[x].f[p];
 91     }
 92     int mid=(t[x].l+t[x].r)>>1;
 93     if(r<=mid) return query(t[x].lc,l,r,p,op);
 94     else if(l>mid) return query(t[x].rc,l,r,p,op);
 95     else return query(t[x].lc,l,mid,p,op)+query(t[x].rc,mid+1,r,p,op);
 96 }
 97 
 98 int main()
 99 {
100     int T,kase=0;
101     scanf("%d",&T);
102     while(T--)
103     {
104         scanf("%d%d",&n,&m);
105         len=0;
106         build(1,2*n-1);
107         printf("Case #%d:\n",++kase);
108         for(int i=1;i<=m;i++)
109         {
110             int opt;
111             scanf("%d",&opt);
112             int l,r;
113             if(opt==1)
114             {
115                 scanf("%d%d",&l,&r);
116                 l--;r--;
117                 printf("%d %d %d\n",l,r,0);
118                 change(1,l,r,0);
119             }
120             else if(opt==2)
121             {
122                 scanf("%d%d",&l,&r);
123                 l+=n;r+=n;
124                 printf("%d %d %d\n",l,r,1);
125                 change(1,l,r,1);
126             }
127             else
128             {
129                 int a,b;
130                 scanf("%d%d%d%d",&l,&a,&r,&b);
131                 int ans=0;
132                 ans+=(query(1,a+r-1,l+b-1,0,2)+query(1,l-r+n,a-b+n,1,2))*mymin(a-l+1,b-r+1);
133                 //zhu
134                 int kk=mymin(a+r-2,l+b-2);
135                 ans+=query(1,l+r-1,kk,0,0)-query(1,l+r-1,kk,0,2)*(l+r-2);//左上
136                     kk=mymax(a+r,l+b);
137                 ans+=query(1,kk,a+b-1,0,1)-query(1,kk,a+b-1,0,2)*(2*n-(a+b-1)-1);//右下
138                 //fu
139                     kk=mymin(a-b+n-1,l-r+n-1);
140                 ans+=query(1,l-b+n,kk,1,0)-query(1,l-b+n,kk,1,2)*(l-b+n-1);//右上
141                 
142                     kk=mymax(a-b+n+1,l-r+n+1);
143                 ans+=query(1,kk,a-r+n,1,1)-query(1,kk,a-r+n,1,2)*(2*n-(a-r+n)-1);//左下
144                 printf("%d\n",ans);
145             }
146         }
147     }
148     return 0;
149 }
View Code

 

有空的话,再填坑吧。。

 

2016-11-10 09:54:11

 

 

转载于:https://www.cnblogs.com/Konjakmoyu/p/6049751.html

你可能感兴趣的:(【BZOJ 2333 】[SCOI2011]棘手的操作(离线+线段树|可并堆-左偏树))