zoj3261 并查集离线处理

Connections in Galaxy War
Time Limit:3000MS     Memory Limit:32768KB     64bit IO Format:%lld & %llu
Appoint description: 

Description

In order to strengthen the defense ability, many stars in galaxy allied together and built many bidirectional tunnels to exchange messages. However, when the Galaxy War began, some tunnels were destroyed by the monsters from another dimension. Then many problems were raised when some of the stars wanted to seek help from the others.

In the galaxy, the stars are numbered from 0 to N-1 and their power was marked by a non-negative integer pi. When the star A wanted to seek help, it would send the message to the star with the largest power which was connected with star A directly or indirectly. In addition, this star should be more powerful than the star A. If there were more than one star which had the same largest power, then the one with the smallest serial number was chosen. And therefore, sometimes star A couldn't find such star for help.

Given the information of the war and the queries about some particular stars, for each query, please find out whether this star could seek another star for help and which star should be chosen.

Input

There are no more than 20 cases. Process to the end of file.

For each cases, the first line contains an integer N (1 <= N <= 10000), which is the number of stars. The second line contains N integersp0p1, ... , pn-1 (0 <= pi <= 1000000000), representing the power of the i-th star. Then the third line is a single integer M (0 <= M <= 20000), that is the number of tunnels built before the war. Then M lines follows. Each line has two integers ab (0 <= ab <= N - 1, a !=b), which means star a and star b has a connection tunnel. It's guaranteed that each connection will only be described once.

In the (M + 2)-th line is an integer Q (0 <= Q <= 50000) which is the number of the information and queries. In the following Q lines, each line will be written in one of next two formats.

  • "destroy a b" - the connection between star a and star b was destroyed by the monsters. It's guaranteed that the connection between star a and star b was available before the monsters' attack.
  • "query a" - star a wanted to know which star it should turn to for help

There is a blank line between consecutive cases.

Output

For each query in the input, if there is no star that star a can turn to for help, then output "-1"; otherwise, output the serial number of the chosen star.

Print a blank line between consecutive cases.

Sample Input

2
10 20
1
0 1
5
query 0
query 1
destroy 0 1
query 0
query 1

Sample Output

1
-1
-1
-1
 
题意:有n个点,每个点有权值,已知有m条边,使x,y相连。现在有q次查询,如果为query x,表示查询x所在的树中,权值最大的点是哪个,如果多个权值相同,那么输出序号最小的点。如果为destroy x,y表示断开x,y这条边。
 
思路:对于处理权值要最大,序列最小,可以使用并查集在合并的时候,让满足题意的座位父亲节点。这里有一个小技巧,对于这题可以先离线记录问题,然后倒着处理问题。对于需要destroy的2个点,先不相连,然后倒着处理查询,如果为destroy,那就相连x,y 2个点。这样题目就转换成了很普通的并查集。
 
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<string>
#include<time.h>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define INF 1000000001
#define ll long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
const int MAXN = 20010;
struct node
{
    char s[10];
    int x;
    int y;
}q[50010],rel[20010];
int pa[MAXN],n,m;
int a[MAXN];
map<int,int>mp[MAXN];
void Init()
{
    for(int i = 0; i < n; i++){
        scanf("%d",&a[i]);
        pa[i] = i;
        mp[i].clear();
    }
}
int ans[50010];
int find(int x)
{
    if(x != pa[x])pa[x] = find(pa[x]);
    return pa[x];
}
void Union(int x,int y)
{
    int fx = find(x);
    int fy = find(y);
    if(fx != fy){
        if(a[fx] > a[fy]){
            pa[fy] = fx;
        }
        else if(a[fy] > a[fx]){
            pa[fx] = fy;
        }
        else if(fx > fy){
            pa[fx] = fy;
        }
        else {
            pa[fy] = fx;
        }
    }
}
int main()
{
    int t,ff = 0;
    while(~scanf("%d",&n)){
        if(ff)printf("
");
        ff = 1;
        Init();
        scanf("%d",&m);
        for(int i = 1; i <= m; i++){
            scanf("%d%d",&rel[i].x,&rel[i].y);
            if(rel[i].x > rel[i].y)swap(rel[i].x,rel[i].y);
        }
        int fq;
        scanf("%d",&fq);
        for(int i = 1; i <= fq; i++){
            scanf("%s",q[i].s);
            if(q[i].s[0] == 'q'){
                scanf("%d",&q[i].x);
            }
            else {
                scanf("%d %d",&q[i].x,&q[i].y);
                if(q[i].x > q[i].y){
                    swap(q[i].x,q[i].y);
                }
                mp[q[i].x][q[i].y] = 1;
            }
        }
        for(int i = 1; i <= m; i++){
            if(!mp[rel[i].x][rel[i].y]){
                Union(rel[i].x,rel[i].y);
            }
        }
        int k = 0;
        for(int i = fq; i >= 1; i--){
            if(q[i].s[0] == 'q'){
                int x = q[i].x;
                int fx = find(x);
                if(a[fx] > a[x]){
                    ans[k++] = fx;
                }
                else ans[k++] = -1;
            }
            else {
                Union(q[i].x,q[i].y);
            }
        }
        for(int i = k - 1; i >= 0; i--){
            printf("%d
",ans[i]);
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/sweat123/p/5478204.html