左偏樹

bzoj1455 羅馬游戲
Description
羅馬皇帝很喜歡玩殺人游戲。 他的軍隊(duì)里面有n個(gè)人宇驾,每個(gè)人都是一個(gè)獨(dú)立的團(tuán)倍靡。最近舉行了一次平面幾何測(cè)試,每個(gè)人都得到了一個(gè)分?jǐn)?shù)课舍。 皇帝很喜歡平面幾何塌西,他對(duì)那些得分很低的人嗤之以鼻。他決定玩這樣一個(gè)游戲筝尾。 它可以發(fā)兩種命令: 1. Merger(i, j)捡需。把i所在的團(tuán)和j所在的團(tuán)合并成一個(gè)團(tuán)。如果i, j有一個(gè)人是死人筹淫,那么就忽略該命令站辉。 2. Kill(i)。把i所在的團(tuán)里面得分最低的人殺死损姜。如果i這個(gè)人已經(jīng)死了饰剥,這條命令就忽略。 皇帝希望他每發(fā)布一條kill命令摧阅,下面的將軍就把被殺的人的分?jǐn)?shù)報(bào)上來汰蓉。(如果這條命令被忽略,那么就報(bào)0分)
Input
第一行一個(gè)整數(shù)n(1<=n<=1000000)棒卷。n表示士兵數(shù)古沥,m表示總命令數(shù)瘸右。 第二行n個(gè)整數(shù),其中第i個(gè)數(shù)表示編號(hào)為i的士兵的分?jǐn)?shù)岩齿。(分?jǐn)?shù)都是[0..10000]之間的整數(shù)) 第三行一個(gè)整數(shù)m(1<=m<=100000) 第3+i行描述第i條命令太颤。命令為如下兩種形式: 1. M i j 2. K i
Output
如果命令是Kill,對(duì)應(yīng)的請(qǐng)輸出被殺人的分?jǐn)?shù)盹沈。(如果這個(gè)人不存在龄章,就輸出0)

#include<iostream>
#include<algorithm>
#include<string.h>
#include<cstdio>
using namespace std;
const int maxn=1000010;
int n,m;
int fa[maxn],die[maxn];
int val[maxn],lef[maxn],rig[maxn],dis[maxn];
int father(int u)
{
    while(fa[u]!=u)
    {
        fa[u]=fa[fa[u]];
        u=fa[u];
    }
    return u;
}
int merge(int x,int y)
{
    if(!x) return y;
    if(!y) return x;
    if(val[x]>val[y]) swap(x,y);
    rig[x]=merge(rig[x],y);
    fa[rig[x]]=x;//并查
    if(dis[rig[x]]>dis[lef[x]]) swap(lef[x],rig[x]);
    dis[x]=dis[rig[x]]+1;//如果x沒有右孩子,則rig[x]=0,而dis[0]=-1,則dis[x]=0;
    return x;
}
int main()
{
    int u,v,fu,fv,t;
      scanf("%d",&n);
      for(int i=1;i<=n;i++)
      {
          scanf("%d",val+i);
          fa[i]=i;
          dis[i]=0;
          die[i]=0;
          lef[i]=0;
          rig[i]=0;
      }
      dis[0]=-1;
      char op[3];
      scanf("%d",&m);
      for(int i=1;i<=m;i++)
      {
          scanf("%s",op);
          if(op[0]=='M')
          {
            scanf("%d%d",&u,&v);
            if(die[u]||die[v]) continue;
            fu=father(u);
            fv=father(v);
            if(fu==fv) continue;
            t=merge(fu,fv);
            fa[t]=t;//成為根節(jié)點(diǎn)
          }
          else{

            scanf("%d",&v);
            if(die[v]) {
                printf("0\n");
            }
            else{
                fv=father(v);
                die[fv]=1;
                printf("%d\n",val[fv]);
                t=merge(lef[fv],rig[fv]);
                fa[t]=t;//成為根節(jié)點(diǎn)
            }
          }
      }
}

https://vjudge.net/problem/HDU-1512
題意:有n個(gè)猴子乞封,一開始每個(gè)猴子只認(rèn)識(shí)自己做裙。每個(gè)猴子有一個(gè)力量值,力量值越大表示這個(gè)猴子打架越厲害肃晚。如果2個(gè)猴子不認(rèn)識(shí)锚贱,他們就會(huì)找他們認(rèn)識(shí)的猴子中力量最大的出來單挑,單挑不論輸贏关串,單挑的2個(gè)猴子力量值減半拧廊,這2撥猴子就都認(rèn)識(shí)了,不打不相識(shí)嘛〗蓿現(xiàn)在給m組詢問吧碾,如果2只猴子相互認(rèn)識(shí),輸出-1墓卦,否則他們各自找自己認(rèn)識(shí)的最牛叉的猴子單挑倦春,求挑完后這撥猴子力量最大值。
題解 :左偏樹+并查集

#include<iostream>
#include<algorithm>
#include<string.h>
#include<cstdio>
using namespace std;
const int maxn=100010;
int n,m;
int fa[maxn];
int val[maxn],lef[maxn],rig[maxn],dis[maxn];
int father(int u)
{
    while(fa[u]!=u)
    {
        fa[u]=fa[fa[u]];
        u=fa[u];
    }
    return u;
}
int merge(int &x,int &y)
{
    if(!x) return y;
    if(!y) return x;
    if(val[x]<val[y]) swap(x,y);
    rig[x]=merge(rig[x],y);
    fa[rig[x]]=x;//并查落剪!
    if(dis[rig[x]]>dis[lef[x]]) swap(lef[x],rig[x]);
    dis[x]=dis[rig[x]]+1;//如果x沒有右孩子睁本,則rig[x]=0,而dis[0]=-1,則dis[x]=0;
    return x;
}
int pop(int &t)
{
    int l=lef[t],r=rig[t];
    fa[l]=l;//因?yàn)橐獣簳r(shí)刪掉根,所以左右子樹先作為根
    fa[r]=r;
    lef[t]=rig[t]=dis[t]=0;
    return merge(l,r);
}
int main()
{
    int u,v,fu,fv,a,b,c;
    while(scanf("%d",&n)!=EOF){

      for(int i=1;i<=n;i++)
      {
          scanf("%d",val+i);
          fa[i]=i;
          dis[i]=0;
          lef[i]=0;
          rig[i]=0;
      }
      dis[0]=-1;
      scanf("%d",&m);
      for(int i=1;i<=m;i++)
      {
            scanf("%d%d",&u,&v);
            fu=father(u);
            fv=father(v);
            if(fu==fv)
            {
                printf("-1\n");
                continue;
            }
            val[fu]>>=1;
            val[fv]>>=1;
            a=pop(fu);
            b=pop(fv);
            c=merge(a,b);
            c=merge(fu,c);
            c=merge(fv,c);
            printf("%d\n",val[c]);
      }
    }
}

https://vjudge.net/problem/HDU-3031
題意:喜羊羊和灰太狼比較所持有的卡片的大小忠怖,每張卡片上都有一定的點(diǎn)數(shù)添履,有5種操作,如下:

  1. T K: 拿到第 k 堆所有牌
  2. C: 喜羊羊和灰太狼手中最大的牌進(jìn)行比較脑又,贏得一方可以把對(duì)方的所有牌全部取過來
  3. L: 失去手中最大的一張牌
  4. A P: 手中最大的牌點(diǎn)數(shù)加上P
  5. E Q: 手中最大的牌點(diǎn)數(shù)改為Q點(diǎn)
    共有R輪比賽暮胧,每輪都是雙方輪流操作,灰太狼先抽问麸,最后輸出輸贏即可往衷。
#include<algorithm>
#include<string.h>
#include<cstdio>
using namespace std;
const int maxn=1000010;
int val[maxn],lef[maxn],rig[maxn],dis[maxn];
int merge(int &x,int &y)
{
    if(!x) return y;
    if(!y) return x;
    if(val[x]<val[y]) swap(x,y);
    rig[x]=merge(rig[x],y);
    if(dis[lef[x]]<dis[rig[x]]) swap(lef[x],rig[x]);
    dis[x]=dis[rig[x]]+1;
    return x;
}
int pop(int &x)
{
    int l=lef[x],r=rig[x];
    lef[x]=rig[x]=dis[x]=0;
    return merge(l,r);
}
int main()
{
    char op[5];
    int sum[2],root[2],num[110],group[110],curr,v,cas,n,m;
    int Happy, Wolffy;
    Happy = Wolffy = 0;
    scanf("%d",&cas);
    while(cas--)
    {
        memset(group,0,sizeof(group));
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++)
            scanf("%d",num+i);
        curr=1;
        dis[0]=-1;
        for(int i=1;i<=m;i++)
        {
            for(int j=1;j<=num[i];j++)
            {
                scanf("%d",&v);
                lef[curr]=rig[curr]=dis[curr]=0;
                val[curr]=v;
                group[i]=merge(group[i],curr);
                curr++;
            }
        }
        sum[0]=sum[1]=0;
        root[0]=root[1]=0;
        for(int i=0;i<n;i++)
        {
            scanf("%s",op);
            if(op[0]=='T')
            {
                scanf("%d",&v);
                root[i&1]=merge(root[i&1],group[v]);
                group[v]=0;
                sum[i&1]+=num[v];
                num[v]=0;
            }
            else if(op[0]=='C')
            {
                if(val[root[0]]>=val[root[1]])
                {
                    root[0]=merge(root[0],root[1]);
                    sum[0]+=sum[1];
                    root[1]=0;
                    sum[1]=0;
                }
                else
                {
                     root[1]=merge(root[0],root[1]);
                    sum[1]+=sum[0];
                    root[0]=0;
                    sum[0]=0;
                }
            }
             else if(op[0]=='L')
            {
                root[i&1]=pop(root[i&1]);
                sum[i&1]--;
            }
             else if(op[0]=='A')
            {
                scanf("%d",&v);
                val[root[i&1]]+=v;
            }
             else
            {
                scanf("%d",&v);
                int t=pop(root[i&1]);
                val[root[i&1]]=v;
                root[i&1]=merge(t,root[i&1]);
            }
        }
        printf("%d:%d\n",sum[0],sum[1]);
        if(sum[0]>=sum[1]) Wolffy++;
        else Happy++;
    }
    if(Wolffy>Happy) printf("Hahaha...I win!!\n");
    else printf("I will be back!!\n");
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市严卖,隨后出現(xiàn)的幾起案子席舍,更是在濱河造成了極大的恐慌,老刑警劉巖哮笆,帶你破解...
    沈念sama閱讀 218,525評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件来颤,死亡現(xiàn)場(chǎng)離奇詭異汰扭,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)福铅,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,203評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門萝毛,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人滑黔,你說我怎么就攤上這事笆包。” “怎么了略荡?”我有些...
    開封第一講書人閱讀 164,862評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵庵佣,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我汛兜,道長(zhǎng)巴粪,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,728評(píng)論 1 294
  • 正文 為了忘掉前任粥谬,我火速辦了婚禮肛根,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘帝嗡。我一直安慰自己,他們只是感情好璃氢,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,743評(píng)論 6 392
  • 文/花漫 我一把揭開白布哟玷。 她就那樣靜靜地躺著,像睡著了一般一也。 火紅的嫁衣襯著肌膚如雪巢寡。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,590評(píng)論 1 305
  • 那天椰苟,我揣著相機(jī)與錄音抑月,去河邊找鬼。 笑死舆蝴,一個(gè)胖子當(dāng)著我的面吹牛谦絮,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播洁仗,決...
    沈念sama閱讀 40,330評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼层皱,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了赠潦?” 一聲冷哼從身側(cè)響起叫胖,我...
    開封第一講書人閱讀 39,244評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎她奥,沒想到半個(gè)月后瓮增,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體怎棱,經(jīng)...
    沈念sama閱讀 45,693評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,885評(píng)論 3 336
  • 正文 我和宋清朗相戀三年绷跑,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了拳恋。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,001評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡你踩,死狀恐怖诅岩,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情带膜,我是刑警寧澤吩谦,帶...
    沈念sama閱讀 35,723評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站膝藕,受9級(jí)特大地震影響式廷,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜芭挽,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,343評(píng)論 3 330
  • 文/蒙蒙 一滑废、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧袜爪,春花似錦蠕趁、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,919評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至昙篙,卻和暖如春腊状,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背苔可。 一陣腳步聲響...
    開封第一講書人閱讀 33,042評(píng)論 1 270
  • 我被黑心中介騙來泰國(guó)打工缴挖, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人焚辅。 一個(gè)月前我還...
    沈念sama閱讀 48,191評(píng)論 3 370
  • 正文 我出身青樓映屋,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親同蜻。 傳聞我的和親對(duì)象是個(gè)殘疾皇子秧荆,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,955評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 2.1.2 可并堆的定義 可并堆(Mergeable Heap)也是一種抽象數(shù)據(jù)類型,它除了支持優(yōu)先隊(duì)列的三個(gè)基本...
    Gitfan閱讀 1,357評(píng)論 0 0
  • 左偏樹的性質(zhì) 本節(jié)點(diǎn)的鍵值key小于其左右子節(jié)點(diǎn)鍵值key(與二叉堆相同); 本節(jié)點(diǎn)的左子節(jié)點(diǎn)的距離大于等于本節(jié)點(diǎn)...
    胡哈哈哈閱讀 2,441評(píng)論 0 0
  • 計(jì)算機(jī)二級(jí)C語言上機(jī)題庫(kù)(南開版) 1.m個(gè)人的成績(jī)存放在score數(shù)組中埃仪,請(qǐng)編寫函數(shù)fun,它的功能是:將低于平...
    MrSunbeam閱讀 6,371評(píng)論 1 42
  • 一年級(jí)語文上冊(cè)生字表 生字表一(共400字) 啊(ā)愛(ài)安(ān)岸(àn)爸(bà)八(bā)巴(bā)...
    meychang閱讀 2,798評(píng)論 0 6
  • 同事們都叫我九哥乙濒,我是女的。 我的客戶,只相信我颁股,背叛我的客戶么库,在別處失敗了還是回來找我。 我在單位甘有,小可以寫政策...
    九九弱水三千閱讀 184評(píng)論 5 2