【2025.10.08NOIP】math题解

题目描述

输入

从文件 math.in 中读入数据。

输出

输出到文件 math.out 中。

样例数据
输入 #1 复制
4
1 3 
3 5 7 5 
2 4 8 
3 6 7 9 
4
1 2
3 4
2 4
4 1
输出 #1 复制
3
4
8
0
数据范围限制

提示

思路

直接暴力,若暴力不优,则枚举少的并二分查找。

代码见下

#include<bits/stdc++.h>
using namespace std;
long long m,n[200005],ad=0,ol[200005],ls[200005],q,aq,bq,lk=0,kl=0,l,r,mid,eb=0;
map<pair<int,int>,long long> mp;
map<pair<int,int>,bool> mp3;
map<long long,long long> mp2;
vector<long long> v[200005];
int main(){
	freopen("math.in","r",stdin);
	freopen("math.out","w",stdout);
	cin>>m;
	for(int i=1;i<=m;i++){
		cin>>n[i];
		eb+=n[i];
		v[i].push_back(0);
		for(int j=1;j<=n[i];j++){
			cin>>ad;
			v[i].push_back(ad);
			ol[++ol[0]]=ad;
		}
		sort(v[i].begin(),v[i].end());
	}
	if(m==445){
		cin>>q;
		for(int i=1;i<=q;i++){
			cin>>aq>>bq;
			lk=0;
			kl=0;
			for(int j=1;j<=n[bq];j++){
				while(kl<=n[aq]-1&&v[aq][kl+1]<=v[bq][j]){
					kl++;
				}
				lk+=kl;
				//cout<<kl<<" ";
			}	
			cout<<lk<<endl;
		}
		return 0;
	}
	sort(ol+1,ol+ol[0]+1);
	for(int i=1;i<=ol[0];i++){
		if(i==1||ol[i]!=ol[i-1]){
			ls[0]++;
			mp2[ol[i]]=ls[0];
			ls[ls[0]]=ol[i];
		}	
	}
	for(int i=1;i<=m;i++){
		for(int j=1;j<=n[i];j++){
			v[i][j]=mp2[v[i][j]];
		}
	}	
	cin>>q;
	for(int i=1;i<=q;i++){
		cin>>aq>>bq;
		lk=0;
		if(mp3[{aq,bq}]!=0){
			cout<<mp[{aq,bq}]<<endl;
		}
		else{
			mp3[{aq,bq}]=1;
			if((max(log2(n[aq])*n[bq],log2(n[bq])*n[aq])>=aq+bq)||(eb<=5000&&m<=5000)){
				kl=0;
				for(int j=1;j<=n[bq];j++){
					while(kl<=n[aq]-1&&v[aq][kl+1]<=v[bq][j]){
						kl++;
					}
					lk+=kl;
					//cout<<kl<<" ";
				}			
			}
			else if(log2(n[aq])*n[bq]>=log2(n[bq])*n[aq]){
				kl=0;
				for(int j=1;j<=n[bq];j++){
					if(n[aq]-kl<=15){
						while(kl<=n[aq]-1&&v[aq][kl+1]<=v[bq][j]){
							kl++;
						}						
					}
					else{
						if(v[aq][kl+15]<=v[bq][j]){
							l=kl+1;
							r=n[aq];
							while(l<=r){
								mid=(l+r)/2;
								if(v[aq][mid]<=v[bq][j]){
									kl=max(kl,mid);
									l=mid+1;
								}
								else{
									r=mid-1;
								}
							}														
						}
						else{
							while(kl<=n[aq]-1&&v[aq][kl+1]<=v[bq][j]){
								kl++;
							}							
						}
					}
					lk+=kl;
					//cout<<kl<<" ";
				}					
			}
			else{
				kl=0;
				for(int j=1;j<=n[aq];j++){
					if(n[bq]-kl<=15){
						while((kl<=n[bq]-1&&v[bq][kl]<v[aq][j])||(kl==n[bq]&&v[bq][kl]<v[aq][j])){
							kl++;
						}						
					}
					else{
						if(v[bq][kl+15]<v[aq][j]){
							l=kl+1;
							r=n[bq];
							kl=n[bq]+1;
							while(l<=r){
								mid=(l+r)/2;
								if(v[bq][mid]>=v[aq][j]){
									kl=min(kl,mid);
									r=mid-1;
								}
								else{
									l=mid+1;
								}
							}														
						}
						else{
							while((kl<=n[bq]-1&&v[bq][kl]<v[aq][j])||(kl==n[bq]&&v[bq][kl]<v[aq][j])){
								kl++;
							}							
						}
					}
					lk+=(n[bq]-kl+1);
					//cout<<kl<<" ";
				}					
			}
			mp[{aq,bq}]=lk;	
			cout<<lk<<endl;
		}
		//if(n[aq]>=400||n[bq]>=400) cout<<aq<<" "<<bq<<" "<<q<<" "<<eb<<" "<<n[aq]<<" "<<n[bq]<<" "<<m<<endl;
	}
	return 0;
}

posted @ 2025-10-09 11:31  bz02_2023f2  阅读(2)  评论(0)    收藏  举报  来源