rt,我的思路就是每次找两个序列(设拼接后长度是k)的第k/2小的数,每次砍掉k/2个数,但是TLE ON #11 只要对代码有帮助的都会关注
#include<bits/stdc++.h>
#define pii pair<int,int>
#define ll long long
#define pll pair<ll,ll>
using namespace std;
const int N=1e6+15;
const long long INF=0x3f3f3f3f3f3f3f3fll;
inline void FileIO(){
freopen("Latent.in","r",stdin);
freopen("Latent.out","w",stdout);
}
template<typename Type>
inline void read(Type& res){
Type x=0,f=1; char c=' '; while(!isdigit(c)){if(c=='-') f=-1;c=getchar();}
while(isdigit(c)) x=(x<<3)+(x<<1)+(c^48),c=getchar();
res=x*f;
}
int T,n,q;
vector<ll> a[N];
ll Solve(vector<ll> x,int s1,int t1,vector<ll> y,int s2,int t2,int k){
// vector<ll> x=a[xx],y=a[yy];
// printf("Solve: s1=%d,t1=%d,s2=%d,t2=%d,k=%d\n",s1,t1,s2,t2,k);
// if(t1-s1+1>t2-s2+1) return Solve(yy,s2,t2,xx,s1,t1,k);
if(t1-s1+1==0) return y[s2+k-1];
if(t2-s2+1==0) return x[s1+k-1];
if(k==1) return min(x[s1],y[s2]);
int pos1=min(t1,s1+k/2-1);
int pos2=min(t2,s2+k/2-1);
// printf("Pos1=%d Pos2=%d\n",pos1,pos2);
if(x[pos1]<y[pos2]) return Solve(x,pos1+1,t1,y,s2,t2,k-(pos1-s1+1));
else return Solve(x,s1,t1,y,pos2+1,t2,k-(pos2-s2+1));
}
ll Midian(int xx,int yy){
vector<ll> x=a[xx],y=a[yy];
int k=(x.size()+y.size()+1)/2;
// printf("x.size=%d y=size=%d\n",x.size(),y.size());
return Solve(x,0,x.size()-1,y,0,y.size()-1,k);
}
signed main(){
// 不开longlong见祖宗!
// 检查数组大小!
// 禁止在int乘int时不开longlong!
//FileIO();
read(T);
while(T--){
for(int i=1;i<=n;i++) a[i].clear();
read(n),read(q);
int k;
for(int i=1;i<=n;i++){
read(k); ll tmp;
for(int j=1;j<=k;j++){
read(tmp);
a[i].push_back(tmp);
}
sort(a[i].begin(),a[i].end());
}
int x,y; ll res;
while(q--){
read(x),read(y);
res=Midian(x,y);
printf("%lld\n",res);
}
}
return 0;
}