题目链接: https://nanti.jisuanke.com/t/40259”
Ichuan really likes to play games, so he organized a game competition with NN participating players.
Follows are the rule of the game competition.
-
There are three modes in the game, in each mode, players have different ability values, in addition, each player may have different ability value in different mode.
-
There are a total of N-1N−1 matches. In each match, two players who have not yet been eliminated will play against each other in one of the modes. The player who has high ability in this mode will win, and the other one will be eliminated.
-
The only player who remains in the game after all N-1N−1 matches will be the winner.
As the organizer of the game, ichuan can manipulate the result of the game. Namely, for each match, he can choose both players and match mode. Of course, he can only choose players who have not yet been eliminated.
Ichuan has some friends, some of them will ask him: "Does player XX will be the winner?" Answering this question will give you a lot of reward, so you need to write a program which can answer these questions.
Input
The first line contains integers NN and Q (1 \le N,Q \le 10^5)Q(1≤N,Q≤105), the number of players and the number of requests.
The next three lines, each line contains NN integers, the X_{th}Xth integer Y(1 \le Y \le 10^6)Y(1≤Y≤106)represents the ability value of player XX in this mode.,
The next qq lines, each line only has one integer X(1 \le X \le n)X(1≤X≤n), which means ichuan's friend wants to know if player XX can be the winner.
Output
For each query, if player XX has a chance to be the winner, output "YES", otherwise output "NO"
输出时每行末尾的多余空格,不影响答案正确性
样例输入复制
4 4
1 2 3 4
1 2 4 3
2 1 3 4
1
2
3
4
样例输出复制
NO
NO
YES
YES
题解:
n个人参加竞技比赛,比赛由三种模式,每种模式,n 个人有3种不同得能力值,举行n−1场比赛,每场比赛选择两个人决斗,能力值低的人淘汰,q 个询问,询问该角色是否有可能生存到最后。
思路:
正解好像是图论,建图然后缩点。
我用了贪心的方法,加上有个人已经有可能是冠军了,那么如果一个人的某一能力,能战胜这个冠军,那么他也一定可以成为冠军。基于这个思想,先对每一种能力值排序,最后一个人一定可以成为冠军,然后我们可以得到一个成为冠军的能力值的最小值(暂时的),然后只要某一能力比这个能力的最小值小,那么他也可以成为冠军,然后用它的值来更新最小值。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<string>
#include<vector>
#define mod (1000000007)
using namespace std;
typedef long long ll;
const int maxn=200100;
set<int> st;
struct node{
int a,b,c,id;
void in(node tm){
a=tm.a;
b=tm.b;
c=tm.c;
id=tm.id;
}
}a1[maxn],a2[maxn],a3[maxn];
int cmp1(node a,node b){
return a.a<b.a;
}
int cmp2(node a,node b){
return a.b<b.b;
}
int cmp3(node a,node b){
return a.c<b.c;
}
int main()
{
int n,q;
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++) scanf("%d",&a1[i].a),a1[i].id=i;
for(int i=1;i<=n;i++) scanf("%d",&a1[i].b);
for(int i=1;i<=n;i++) scanf("%d",&a1[i].c);
for(int i=1;i<=n;i++){
a2[i].in(a1[i]);
a3[i].in(a1[i]);
}
sort(a1+1,a1+n+1,cmp1);
sort(a2+1,a2+n+1,cmp2);
sort(a3+1,a3+n+1,cmp3);
int la=n,lb=n,lc=n;
int ma=min(a1[n].a,min(a2[n].a,a3[n].a));
int mb=min(a1[n].b,min(a2[n].b,a3[n].b));
int mc=min(a1[n].c,min(a2[n].c,a3[n].c));
while(1){
int ff=0;
for(;la>0&&a1[la].a>=ma;la--){
ff=1;
st.insert(a1[la].id);
ma=min(ma,a1[la].a);
mb=min(mb,a1[la].b);
mc=min(mc,a1[la].c);
}
for(;lb>0&&a2[lb].b>=mb;lb--){
ff=1;
st.insert(a2[lb].id);
ma=min(ma,a2[lb].a);
mb=min(mb,a2[lb].b);
mc=min(mc,a2[lb].c);
}
for(;lc>0&&a3[lc].c>=mc;lc--){
ff=1;
st.insert(a3[lc].id);
ma=min(ma,a3[lc].a);//用新加入的数更新最小值,这个值应该a3[lc],但是a1[lc] 就变成另一个数了
mb=min(mb,a3[lc].b);
mc=min(mc,a3[lc].c);
}
if(!ff) break;
}
while(q--){
int x;
scanf("%d",&x);
if(st.find(x)==st.end()) puts("NO");
else puts("YES");
}
return 0;
}
队友的图论做法:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<stack>
#include<map>
#include<vector>
#include<set>
#include<string>
#include<cmath>
#include<cstring>
#define FF first
#define SS second
#define ll long long
#define pb push_back
#define pm make_pair
using namespace std;
typedef pair<int,int> PII;
const int MAX = 2e5 + 5;
struct Node {
int a,b,c;
int id;
} R[MAX];
bool cmp1(Node a,Node b) {
return a.a < b.a;
}
bool cmp2(Node a,Node b) {
return a.b < b.b;
}
bool cmp3(Node a,Node b) {
return a.c < b.c;
}
int n,q;
vector<int> vv[MAX];
int DFN[MAX],LOW[MAX],stk[MAX],vis[MAX],clk,Index,scc,col[MAX];
int in[MAX],ans[MAX];
void tarjan(int x) {
DFN[x] = LOW[x] = ++clk;stk[++Index] = x;vis[x] = 1;
for(int i = 0; i<vv[x].size(); i++) {
int v = vv[x][i];
if(!DFN[v]) {
tarjan(v);LOW[x] = min(LOW[x],LOW[v]);
}
else if(vis[v]) LOW[x] = min(LOW[x],DFN[v]);
}
if(LOW[x] == DFN[x]) {
scc++;
while(1) {
int tmp = stk[Index--];vis[tmp] = 0;
col[tmp] = scc;
if(tmp == x) break;
}
}
}
int main()
{
cin>>n>>q;
for(int i = 1; i<=n; i++) scanf("%d",&R[i].a),R[i].id = i;
for(int i = 1; i<=n; i++) scanf("%d",&R[i].b);
for(int i = 1; i<=n; i++) scanf("%d",&R[i].c);
sort(R+1,R+n+1,cmp1);
for(int i = 2; i<=n; i++) vv[R[i].id].pb(R[i-1].id);
sort(R+1,R+n+1,cmp2);
for(int i = 2; i<=n; i++) vv[R[i].id].pb(R[i-1].id);
sort(R+1,R+n+1,cmp3);
for(int i = 2; i<=n; i++) vv[R[i].id].pb(R[i-1].id);
for(int i = 1; i<=n; i++) if(!DFN[i]) tarjan(i);
for(int u = 1; u<=n; u++) {
for(int j = 0; j<vv[u].size(); j++){
int v = vv[u][j];
if(col[u] != col[v]) in[col[v]]++;
}
}
while(q--) {
int x; scanf("%d",&x);
if(in[col[x]] == 0) printf("YES\n");
else printf("NO\n");
}
return 0 ;
}