• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            隨筆 - 97, 文章 - 22, 評(píng)論 - 81, 引用 - 0
            數(shù)據(jù)加載中……

            PKU 2985 The k-th Largest Group

            題目鏈接:http://poj.org/problem?id=2985

            /*
            題意:
                給定N(N <= 200000)個(gè)操作,每個(gè)操作是以下兩種形式:
            0 x y : 合并x所在的組和y所在的組,如果x和y同組,不合并。
            1 k:輸出第k大的組的元素個(gè)數(shù)。

            解法:
            樹(shù)狀數(shù)組 + 并查集

            思路:
                 將元素的個(gè)數(shù)對(duì)應(yīng)樹(shù)狀數(shù)組的下標(biāo),每次合并操作,在樹(shù)狀
            數(shù)組中對(duì)應(yīng)兩個(gè)集合大小的位置分別減1,兩集合之后的位置+1,
            詢問(wèn)操作只需要二分答案,然后每次統(tǒng)計(jì)比k大的數(shù)的個(gè)數(shù)判可行
            即可。
            */


            #include 
            <iostream>

            using namespace std;

            #define maxn 200010

            int c[maxn];
            int prev[maxn], num[maxn];
            int n;

            int lowbit(int x) {
                
            return x & (-x);
            }

            void add(int pos, int num) {
                
            while(pos <= n) {
                    c[pos] 
            += num;
                    pos 
            += lowbit(pos);
                }

            }


            int sum(int pos) {
                
            int s = 0;
                
            while(pos > 0{
                    s 
            += c[pos];
                    pos 
            -= lowbit(pos);
                }

                
            return s;
            }


            int find(int x) {
                
            int q = x;
                
            while(x != prev[x]) {
                    x 
            = prev[x];
                }

                
            return x;
            }


            void Union(int x, int y) {
                x 
            = find(x);
                y 
            = find(y);

                
            if(x != y) {
                    
            if(num[x] == num[y])
                        add(num[x], 
            -2);
                    
            else {
                        add(num[x], 
            -1);
                        add(num[y], 
            -1);
                    }

                    add(num[x] 
            + num[y], 1);

                    
            if(num[x] < num[y]) {
                        prev[x] 
            = y;
                        num[y] 
            += num[x];
                    }
            else {
                        prev[y] 
            = x;
                        num[x] 
            += num[y];
                    }

                }

            }



            int Query(int k) {
                
            int l = 1;
                
            int r = n;
                
            int ans = 0;
                
            int all = sum(n);
                
            while(l <= r) {
                    
            int m = (l + r) >> 1;
                    
            if(k <= all - sum(m-1)) {
                        l 
            = m + 1;
                        ans 
            = m;
                    }
            else
                        r 
            = m - 1;
                }

                
            return ans;
            }


            int main() {
                
            int i, m;
                
            int op, x, y;
                
            while(scanf("%d %d"&n, &m) != EOF) {
                    
            for(i = 1; i <= n; i++{
                        c[i] 
            = 0;
                        prev[i] 
            = i;
                        num[i] 
            = 1;
                    }

                    add(
            1, n);
                    
            while(m--{
                        scanf(
            "%d"&op);
                        
            if(op == 0{
                            scanf(
            "%d %d"&x, &y);
                            Union(x, y);
                        }
            else {
                            scanf(
            "%d"&x);
                            printf(
            "%d\n", Query(x));
                        }

                    }


                }

                
            return 0;
            }

            posted on 2011-04-07 09:31 英雄哪里出來(lái) 閱讀(1231) 評(píng)論(2)  編輯 收藏 引用 所屬分類: 樹(shù)狀數(shù)組

            評(píng)論

            # re: PKU 2985 The k-th Largest Group  回復(fù)  更多評(píng)論   

            那個(gè)x與-x為與位運(yùn)算時(shí)用來(lái)干嘛的???
            2012-07-11 21:08 | 秋秋

            # re: PKU 2985 The k-th Largest Group[未登錄](méi)  回復(fù)  更多評(píng)論   

            真的會(huì)死很多腦細(xì)胞啊周仁兄。。
            2013-06-02 01:41 | Grace
            午夜福利91久久福利| 久久伊人五月丁香狠狠色| 久久WWW免费人成一看片| 久久免费香蕉视频| 久久精品国产精品亚洲下载| 久久精品国产久精国产| 精品国产一区二区三区久久| 大伊人青草狠狠久久| 国产成人久久AV免费| 久久99精品国产麻豆宅宅| 亚洲嫩草影院久久精品| 久久久久国产精品| 青青青青久久精品国产| 国产精品成人99久久久久91gav| 99久久无码一区人妻| 久久久久国产| 久久久亚洲AV波多野结衣| 一本久久知道综合久久| 久久久国产乱子伦精品作者| avtt天堂网久久精品| 久久99国产精一区二区三区| 国产精品久久久天天影视香蕉| 国产精品综合久久第一页| 武侠古典久久婷婷狼人伊人| 久久久久久精品无码人妻| 久久人妻少妇嫩草AV无码专区| 久久国产亚洲高清观看| 91久久精品国产成人久久| 亚洲人成无码www久久久| 亚洲人成精品久久久久| 精品久久一区二区| 欧美国产精品久久高清| 天天躁日日躁狠狠久久| 99久久精品无码一区二区毛片 | 国产精品久久久久免费a∨| 中文精品久久久久人妻不卡| 国产精品一区二区久久| 久久综合一区二区无码| 精品久久8x国产免费观看| 精品久久久久久无码中文字幕 | 久久精品国产亚洲AV高清热|