动态开点线段树合并 WA On#1求调
查看原帖
动态开点线段树合并 WA On#1求调
881015
Resstifnurvˆwˆ.tar.gz楼主2024/3/10 12:24

首先确定不是多测初始化的问题,因为我第一个询问就错了

#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
typedef long long ll;

inline ll read(){
	ll ret=0;
	char ch=' ',c=getchar();
	while(!('0'<=c&&c<='9')) ch=c,c=getchar();
	while('0'<=c&&c<='9') ret=(ret<<1)+(ret<<3)+(c^48),c=getchar();
	return ch=='-'?-ret:ret;
}

int T,n,m,q;
const int N=3e7+10;
int len[N];
vector<ll> a[N];

vector<ll> b;
int getid(ll x){
	int l=0,r=m-1,mid;
	while(l<r){
		mid=(l+r)>>1;
		if(b[mid]>=x) r=mid;
		else l=mid+1;
	}
	return l+1;
}

struct NODE{
	int ls,rs;
	int cnt;
} tr[N];
int idx=0;
int rt[N];

void modify(int &u,int l,int r,int k){
	if(!u) u=++idx;
	tr[u].cnt++;
	if(l==r) return ;
	int mid=(l+r)>>1;
	if(k<=mid) modify(tr[u].ls,l,mid,k);
	else modify(tr[u].rs,mid+1,r,k);
}

ll query(int u,int v,int l,int r,int rk){
	if(l==r) return b[l-1];
	int sz=tr[tr[u].ls].cnt+tr[tr[v].ls].cnt;
	int mid=(l+r)>>1;
	if(rk<=sz) return query(tr[u].ls,tr[v].ls,l,mid,rk);
	else return query(tr[u].rs,tr[v].rs,mid+1,r,rk-sz);
}

int main(){
	T=read();
	int x,l,r;
	while(T--){
		for(int i=1;i<=idx;i++){
			tr[i].cnt=0;
			tr[i].ls=0;
			tr[i].rs=0;
		}
		idx=0;
		b.clear();
		n=read(),q=read();
		for(int i=1;i<=n;i++) rt[i]=0;
		for(int i=1;i<=n;i++){
			a[i].clear();
			len[i]=read();
			for(int j=1;j<=len[i];j++){
				x=read();
				a[i].push_back(x);
				b.push_back(x);
			}
		}
		sort(b.begin(),b.end());
		b.erase(unique(b.begin(),b.end()),b.end());
		m=b.size();
		for(int i=1;i<=n;i++){
			for(int j=0;j<len[i];j++){
				modify(rt[i],1,m,getid(a[i][j]));
			}
		}
		while(q--){
			l=read(),r=read();
			printf("%lld\n",query(rt[l],rt[r],1,m,(len[l]+len[r]+1)/2));
		}
	}
	return 0;
}
2024/3/10 12:24
加载中...