zoukankan      html  css  js  c++  java
  • [SCOI2011]棘手的操作

    题目描述

    有N个节点,标号从1到N,这N个节点一开始相互不连通。第i个节点的初始权值为a[i],接下来有如下一些操作:U x y: 加一条边,连接第x个节点和第y个节点A1 x v: 将第x个节点的权值增加vA2 x v: 将第x个节点所在的连通块的所有节点的权值都增加vA3 v: 将所有节点的权值都增加vF1 x: 输出第x个节点当前的权值F2 x: 输出第x个节点所在的连通块中,权值最大的节点的权值F3: 输出所有节点中,权值最大的节点的权值

    输入输出格式

    输入格式:

    输入的第一行是一个整数N,代表节点个数。接下来一行输入N个整数,a[1], a[2], ..., a[N],代表N个节点的初始权值。再下一行输入一个整数Q,代表接下来的操作数。最后输入Q行,每行的格式如题目描述所示。

    输出格式:

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

    输入输出样例

    输入样例#1:
    3
    0 0 0
    8
    A1 3 -20
    A1 2 20
    U 1 3
    A2 1 10
    F1 3
    F2 3
    A3 -10
    F3
    输出样例#1:
    -10
    10
    10

    说明

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

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

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

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

    用两颗左偏树来维护这些棘手的操作
    一个维护每个堆,一个维护全局最大值.
    U:x,y所处的两个堆合并,合并的时候记得down.
    A1:把这个点的堆顶从第二个堆中删除,然后把这个点从第一个堆中删除,+v之后插入,堆顶也要插入.
    A2:将堆顶打上标记,并从第二个堆中取出,+v后插入第二个堆.
    A3:用一个全局变量即可
    F1:把他上面的节点全部下放后直接查询
    F2:直接查询这个堆的堆顶
    F3:直接查询第二个堆的堆顶.
    代码有点难写…

      1 #include<bits/stdc++.h>
      2 #define maxn 300010
      3 using namespace std;
      4 char S[3];
      5 multiset<int>st;
      6 int key[maxn],ls[maxn],rs[maxn],fa[maxn],lazy[maxn],d[maxn],q[maxn],atag=0;
      7 int sp[maxn*2],l[maxn*2],r[maxn*2],dd[maxn*2],val[maxn*2],faa[maxn*2],rt=0,tt=0;
      8 int Find(int x){//不能路径压缩.
      9   while(fa[x]) x=fa[x];
     10   return x;
     11 }
     12 int Find2(int x){
     13   while(faa[x]) x=faa[x];
     14   return x;
     15 }
     16 inline void down(int x){
     17   if(!lazy[x])return;
     18   int t=lazy[x];lazy[x]=0;
     19   if(ls[x])key[ls[x]]+=t,lazy[ls[x]]+=t;
     20   if(rs[x])key[rs[x]]+=t,lazy[rs[x]]+=t;
     21 }
     22 void pd(int x){
     23   int tot=0;
     24   while(x)q[++tot]=x,x=fa[x];
     25   while(tot)down(q[tot--]);
     26 }
     27 int unionn(int x,int y){
     28   if(!x) return y;
     29   if(!y) return x;
     30   if(key[x]<key[y]) swap(x,y);
     31   down(x);
     32   rs[x]=unionn(rs[x],y);
     33   fa[rs[x]]=x;
     34   if(d[rs[x]]>d[ls[x]])
     35     swap(rs[x],ls[x]);
     36   d[x]=d[rs[x]]+1;
     37   return x;
     38 }
     39 int unionn2(int x,int y){
     40   if(!x) return y;
     41   if(!y) return x;
     42   if(val[x]<val[y]) swap(x,y);
     43   r[x]=unionn2(r[x],y);
     44   faa[r[x]]=x;
     45   if(dd[r[x]]>dd[l[x]])
     46     swap(r[x],l[x]);
     47   dd[x]=dd[r[x]]+1;
     48   return x;
     49 }
     50 inline void newnode(int keyy,int p){
     51   ++tt;
     52   val[tt]=keyy;
     53   sp[p]=tt;
     54   if(!rt) rt=tt;
     55   else rt=unionn2(rt,tt);
     56 }
     57 inline void erase(int x){
     58   int t=unionn2(l[x],r[x]),f=faa[x];
     59   l[x]=r[x]=0,faa[x]=0;
     60   if(x==l[f])l[f]=t;
     61   else r[f]=t;
     62   faa[t]=f;
     63   rt=Find2(t);
     64 }
     65 int del(int x){
     66   pd(x);
     67   int t=unionn(ls[x],rs[x]),f=fa[x];
     68   ls[x]=rs[x]=0,fa[x]=0;
     69   if(x==ls[f])ls[f]=t;
     70   else rs[f]=t;
     71   fa[t]=f;
     72   return Find(t);
     73 }
     74 inline void Add(int x,int v){
     75   pd(x);
     76   erase(sp[Find(x)]);
     77   key[x]+=v;
     78   int t=unionn(x,del(x));
     79   newnode(key[t],t);
     80 }
     81 inline void Add2(int x,int v){
     82   int t=Find(x);
     83   lazy[t]+=v;
     84   erase(sp[t]);
     85   key[t]+=v;
     86   newnode(key[t],t);
     87 }
     88 inline void query(int x){
     89   pd(x);
     90   printf("%d
    ",key[x]+atag);
     91 }
     92 inline void query2(int x){
     93   printf("%d
    ",key[Find(x)]+atag);
     94 }
     95 int main(){
     96   int n,m,x,y;
     97   scanf("%d",&n);
     98   for(int i=1;i<=n;i++)
     99     scanf("%d",&key[i]),newnode(key[i],i);
    100   scanf("%d",&m);
    101   for(int i=1;i<=m;i++){
    102     scanf("%s",S);
    103     if(S[0]=='U'){
    104       scanf("%d%d",&x,&y);
    105       int u=Find(x),v=Find(y);
    106       if(u!=v){
    107     if(unionn(u,v)==u)erase(sp[v]);
    108     else erase(sp[u]);
    109       }
    110     }
    111     if(S[0]=='A'){
    112       if(S[1]=='1')scanf("%d%d",&x,&y),Add(x,y);
    113       if(S[1]=='2')scanf("%d%d",&x,&y),Add2(x,y);
    114       if(S[1]=='3')scanf("%d",&x),atag+=x;
    115     }
    116     if(S[0]=='F'){
    117       if(S[1]=='1')scanf("%d",&x),query(x);
    118       if(S[1]=='2')scanf("%d",&x),query2(x);
    119       if(S[1]=='3') printf("%d
    ",val[rt]+atag);
    120     }
    121   }
    122   return 0;
    123 }
  • 相关阅读:
    c#驱动操作mongodb辅助类MongoDBHelper
    c#多线程lock无效
    利用Aspose.Words将html转成pdf和将html转成word
    前后端值映射的问题
    本机部署流程详解
    Git 安装配置手册
    js对象数组(JSON) 根据某个共同字段 分组
    jquery中的$.fn的用法
    JSON.parse()与JSON.stringify()的区别
    添加编辑 时 数据不可重复验证
  • 原文地址:https://www.cnblogs.com/pantakill/p/7282486.html
Copyright © 2011-2022 走看看