【集训队互测 2012】Attack

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/C20190102/article/details/99939853

文章目录

题目

Description
chnlich非常喜欢玩三国志这款游戏,并喜欢用一些策略出奇制胜。现在,他要开始征服世界的旅途了。他的敌人有 N N 座城市和 N N 个太守, N N 个城市可以看作在二维平面上的 N N 个点。 N N 座城市的标号为 0 , 1 , 2 ,   , N 1 0,1,2,\cdots,N-1 。第 i i 座城市的坐标为 ( x i , y i ) (x_i,y_i) ,镇守这座城市的太守的能力值为 z i z_i
chnlich每次会选择一个边平行于坐标轴的矩形区域,并奇袭其中太守能力值第 K K 小的城市(奇袭结束之后城市与太守依然存在)。
不过,他的敌人经常会偷偷交换两座城市的太守,防止弱点被chnlich发现。
现在,chnlich想要知道,每次奇袭时他的敌人的能力值。

Input
输入的第一行包含两个整数 N N M M N N 表示城市与太守的个数, M M 表示接下来发生了 M M 个事件。
输入的第二行到第 N + 1 N+1 行,每行包含三个整数,第 i + 2 i+2 行的三个整数依次表示编号为 i i 的城市的 x i , y i , z i x_i,y_i,z_i ,含义如题所述。
输入的第 N + 2 N+2 行到第 N + M + 1 N+M+1 行,每行有两种可能形式:

  • 第一种
    QUERY x0 y0 x1 y1 k
    表示chnlich询问一个相对顶点为 ( x 0 , y 0 ) (x_0,y_0) ( x 1 , y 1 ) (x_1,y_1) 的矩形中,第 k k 小能力值太守的能力值。
  • 第二种
    SWAP x y
    表示chnlich的敌人交换了编号为 x x y y 两座城市的太守。

Output
对于每一个QUERY,输出一行。
若不存在第 k k 小能力值的太守,输出It doesn't exist.
否则输出一个整数,表示矩形内能力值第 k k 小太守的能力值。

Sample Input
3 5
1 1 1
2 2 2
3 3 3
QUERY 1 1 3 3 3
SWAP 0 1
QUERY 2 2 4 4 1
SWAP 2 2
QUERY 2 2 3 3 3

Sample Output
3
1
It doesn't exist.

Hint
对于 100 100% 的数据, N 60000 N\leq60000 M 10000 M\leq10000 0 x i , y i , z i 1 0 9 , k 1 0 9 0\leq x_i,y_i,z_i\leq 10^9,k\leq10^9 ,保证所有操作均合法。

分析

怎么说呢,直接按太守能力值排序,暴力 O ( n ) O(n) 找第 k k 大,找到了立即输出,交换的时候不要交换能力值,交换坐标即可。于是就这样水过了。

代码

#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;

#define MAXN 600000
struct Point{
    int x,y,num,id;
}A[MAXN+5];
int Rev[MAXN+5];
bool cmp(Point i,Point j){
    return i.num<j.num;
}

int main(){
    int M,N;
    scanf("%d%d",&N,&M);
    for(int i=1;i<=N;i++)
        A[i].id=i,scanf("%d%d%d",&A[i].x,&A[i].y,&A[i].num);
    sort(A+1,A+N+1,cmp);
    for(int i=1;i<=N;i++)
        Rev[A[i].id-1]=i;//要存是每个点在排完序过后的位置
    while(M--){
        char opt[10];
        scanf("%s",opt);
        if(opt[0]=='Q'){
            int k;
            Point P,Q;
            scanf("%d%d%d%d%d",&P.x,&P.y,&Q.x,&Q.y,&k);
            int Minx=min(P.x,Q.x),Maxx=max(P.x,Q.x),Miny=min(P.y,Q.y),Maxy=max(P.y,Q.y);
            //注意这里,给出的两个点不一定是左下角和右上角
            for(int i=1;i<=N;i++){
                if(A[i].x>=Minx&&A[i].x<=Maxx&&A[i].y>=Miny&&A[i].y<=Maxy){
                    k--;
                    if(!k){
                        printf("%d\n",A[i].num);
                        break;
                    }
                }
            }
            if(k)
                puts("It doesn't exist.");
        }
        else{
            int x,y;
            scanf("%d%d",&x,&y);
            swap(A[Rev[x]].x,A[Rev[y]].x);
            swap(A[Rev[x]].y,A[Rev[y]].y);
            swap(Rev[x],Rev[y]);//交换的时候注意一下即可
        }
    }
}

猜你喜欢

转载自blog.csdn.net/C20190102/article/details/99939853