good-problems 12

1.D. Fixed Prefix Permutations
题解
对于每个排列p,能得到答案最大值等价于排列p与所有q能匹配的最长前缀.
对于前缀问题可以使用字典树(Trie)解决

点击查看代码
#include <bits/stdc++.h>
#define int long long 
#define ll long long
#define pa pair<int,int>
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define YES {puts("YES");return;}
#define NO {puts("NO");return ;}
using namespace std;
const int maxn=1e6+101;
const int N=6e5+1010;
const int MOD=998244353;
const int inf=2147483647;
const double pi=acos(-1);
const double eps=1e-12;

ll read(){
    ll x=0,f=1;char ch=getchar();
    for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
    for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';
    return x*f;
}
int tot,ch[maxn][12];
void insert(vector<int> a){
    int u=0,lenth=a.size();
    for(int i=0;i<lenth;i++){
        int k=a[i];
        if(!ch[u][k])ch[u][k]=++tot;
        u=ch[u][k];
    }
    return;
}
int find(vector<int> a){
	int u=0,lenth=a.size(),ans=0;
	for(int i=0;i<lenth;i++){
		int k=a[i];
		if(!ch[u][k])break;
		u=ch[u][k];ans++;	
	}
	return ans;
}
void init(){
	for(int i=0;i<=tot;i++)for(int j=0;j<=10;j++)ch[i][j]=0;
	tot=0;return ;
}
void solve() {
	init();
	int n=read(),m=read();
	vector<vector<int> > a(n,vector<int>(m)),b(n,vector<int>(m)); 
	for(int i=0;i<n;i++){
		for(int j=0;j<m;j++)a[i][j]=read()-1,b[i][a[i][j]]=j;
		//b[i][j]表示第i个序列的j在b[i][j]的位置上
		//插入b,跟a进行匹配
		//为什么不插入a,跟b匹配,:因为用b来匹配无法保证前缀匹配(也就是匹配不是从头到尾的,中间不连续) 
		insert(b[i]);	
	}
	for(int i=0;i<n;i++)cout<<find(a[i])<<" ";puts("");
	return ; 
}

signed main(){
	int t=read();
	while(t--)solve();
    return 0;
}

2.E. Josuke and Complete Graph
题意:

题解:
g=gcd(i,j)

首先我们可以知道

LgR2 时都是满足条件的,因为 Lg<2gR

现在考虑 g<L 的情况

f=Lg, 只要满足 Lfg<(f+1)gRg 都是满足条件的

一个一个找肯定是不行的

注意对于一定范围的g, 其 f=Lg 是相同的,不难想到整除分块

整除分块的时间复杂度为 O(n)
因为整除分块的时间复杂度取决于不同 f 的个数
对于gL,fL
对于L<g,fL,f<L
因此时间复杂度为 O(n)

这道题的整除分块与普通不同,是上取整,只是[l,r]的获取方式不同

点击查看代码
void solve() {
	int L=read(),R=read(),ans=max(0ll,R/2-L+1);
	for(int l=1,r;l<L;l=r+1){
		int f=(L+l-1)/l;r=l;
		int lr=L/f,rc=L-1;
		while(rc>=lr){
			int mid=(lr+rc)>>1;
			if((L+mid-1)/mid==f)lr=mid+1,r=mid;
			else rc=mid-1;
		}
		ans+=max(0ll,min(r-l+1,R/(f+1)-l+1)); 
	}
	cout<<ans<<endl;
	return ; 
}

3.F. Timofey and Black-White Tree
题解

点击查看代码
void solve() {
	int n=read();
	vector<int>dis(n+1),c(n);
	for(int i=0;i<n;i++)c[i]=read(),dis[i+1]=inf;
	vector<vector<int> >G(n+1);
	for(int i=1;i<n;i++){
		int u=read(),v=read();
		G[u].pb(v);G[v].pb(u);
	}
	int ans=inf;
	for(int i=0;i<n;i++){
		ans=min(ans,dis[c[i]]);
		if(i)cout<<ans<<" ";
		queue<int>q;q.push(c[i]);
		dis[c[i]]=0;
		while(!q.empty()){
			int u=q.front();q.pop();
			for(auto v: G[u]){
				if(dis[u]+1<dis[v] && dis[u]+1<ans){
					dis[v]=dis[u]+1;
					q.push(v);	
				}
			}
		}
	}
	puts("");return ; 
}
posted @   I_N_V  阅读(12)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示