我最开始没注意到是返回编号,改成返回编号之后直接交了一发,竟然过了
回头给同学debug,才发现大问题,我的程序是通过query查到最小值,然后通过值返回编号,具体是通过查询一个tr数组(反向数组)返回去查编号
但是我的程序在不合法的时候会返回-1,这样会导致查询到数组的-1位置
但是神奇的是我没检查程序直接交了,竟然过了,后来重新试了几发,C++20 14 开不开O2都试过了,都能过
但是现在本地dev连样例都过不了了(我改完之后蜜汁自信,没对样例直接交了),但是洛谷上面AC,不知道是什么情况
有知道原理的大犇能够解答一下吗?
代码我放到下面,需要的话可以阅读:
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 2e6 + 5;
const int MAXM = 1e5 ;
int n,m;
int T[MAXN],lch[MAXN],rch[MAXN],nt;
int pri[MAXN],root[MAXN],tr[MAXN];
int confa[MAXN];
int Q,a,b;
char op;
void push_up(int p){T[p]=T[lch[p]]+T[rch[p]];}
int find(int x){return x==confa[x]?x:confa[x]=find(confa[x]);}
void change(int pos,int x,int &p,int s=1,int t=n){
if(!p)p=++nt;
if(s==t)return T[p]=x,void();
int mid=(s+t)>>1;
if(pos<=mid)change(pos,x,lch[p],s,mid);
else change(pos,x,rch[p],mid+1,t);
push_up(p);
}
int merge(int p1,int p2){
if(!(p1&&p2))return p1|p2;
T[p1]+=T[p2];
lch[p1]=merge(lch[p1],lch[p2]);
rch[p1]=merge(rch[p1],rch[p2]);
return p1;
}
int query(int k,int p,int s=1,int t=n){
if(!p)return -1;
if(s==t)return s;
int mid=(s+t)>>1;
if(T[lch[p]]>=k)return query(k,lch[p],s,mid);
else return query(k-T[lch[p]],rch[p],mid+1,t);
}
int main(){
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++)scanf("%d",&pri[i]),change(pri[i],1,root[i]),confa[i]=i,tr[pri[i]]=i;
for(int i=1;i<=m;i++){
scanf("%d %d",&a,&b);
merge(root[find(a)],root[find(b)]);
confa[find(b)]=find(a);
}
scanf("%d",&Q);
while(Q--){
scanf(" %c %d %d",&op,&a,&b);
if(op=='Q')printf("%d\n",tr[query(b,root[find(a)])]);
else merge(root[find(a)],root[find(b)]),confa[find(b)]=find(a);
}
return 0;
}