zoukankan      html  css  js  c++  java
  • 【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<cstdio>
      2 #include<cstdlib>
      3 #include<cstring>
      4 #include<iostream>
      5 #include<algorithm>
      6 #include<cmath>
      7 #include<vector>
      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
    ",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
    ",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
    ",dfn[q[i].x],dfn[q[i].x]);
    193             int now=query(1,dfn[q[i].x],dfn[q[i].x]);
    194             printf("%d
    ",now+ad);
    195         }
    196         else if(q[i].op==4)
    197         {
    198             // printf("ask %d %d
    ",lf[q[i].id],rt[q[i].id]);
    199             int now=query(1,lf[q[i].id],rt[q[i].id]);
    200             printf("%d
    ",now+ad);
    201         }
    202         else if(q[i].op==5)
    203         {
    204             int now=query(1,1,cnt);
    205             printf("%d
    ",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<cstdio>
      2 #include<cstdlib>
      3 #include<cstring>
      4 #include<iostream>
      5 #include<algorithm>
      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
    ",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
    ",t[xx].x+all);
    159             }
    160             else
    161             {
    162                 printf("%d
    ",*(--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<cstdio>
      2 #include<cstdlib>
      3 #include<cstring>
      4 #include<iostream>
      5 #include<algorithm>
      6 #include<cmath>
      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 x<y?x: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:
    ",++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
    ",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
    ",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
    ",ans);
    145             }
    146         }
    147     }
    148     return 0;
    149 }
    View Code

    有空的话,再填坑吧。。

    2016-11-10 09:54:11

  • 相关阅读:
    hiho 1182 : 欧拉路·三
    hiho拓扑排序专题 ——第四十八、四十七周
    hiho欧拉路·二 --------- Fleury算法求欧拉路径
    hdoj1423 最长上升公共子序列
    学习记录--让我打开另一种思路的SQL
    学习记录--如何将exec执行结果放入变量中?
    SQLServer中的Cross Apply、Outer Apply
    学习记录--一列数据转为一个字段
    学习记录--查询没有学全所有课的同学的学号、姓名、以及未学科目
    ISNUMERIC()检测是否为数字
  • 原文地址:https://www.cnblogs.com/Konjakmoyu/p/6049751.html
Copyright © 2011-2022 走看看