noip模擬14

ccjjxx發表於2024-11-16

A 字串構造機

怎麼是原啊。。原我還沒找。

然後考完找打發現上次場切了,這次沒有。。。

就是並查集連邊,考慮限制條件有兩種,一定相等和一定不相等。維護一下。

點選檢視程式碼
#include<bits/stdc++.h>
using namespace std;
int n,m;
const int N=1e3+3;
struct op{
	int x,y,z;
}a[N];
int f[N];
int find(int x)
{
	if(x!=f[x]) return f[x]=find(f[x]);
	return x;
}
int num[N],ans[N];
inline bool cmp(op x,op y)
{
	if(x.x==y.x) return x.y<y.y;
	return x.x<y.x;
}
struct node{
	int a,b;
}anti[N];
int cnt;
int dis[N][N],cnt1[N];
bool ck[N][N];
signed main()
{
	freopen("str.in","r",stdin);
	freopen("str.out","w",stdout);
	cin>>n>>m;
	for(int i=1;i<=n;i++) f[i]=i,ans[i]=-1;
	for(int i=1;i<=m;i++)
	{
		int x,y,z;cin>>x>>y>>z;
		if(y<x) swap(x,y);
		for(int j=0;j<z;j++) f[find(y+j)]=f[find(x+j)];
		if(y+z<=n)
		anti[++cnt].a=x+z,anti[cnt].b=y+z;
	}
	for(int i=1;i<=cnt;i++)
	{
		int u=find(anti[i].a),v=find(anti[i].b);
		if(u==v) return cout<<"-1",0;
		if(!ck[u][v]) dis[u][++cnt1[u]]=v,dis[v][++cnt1[v]]=u;
		ck[u][v]=1;
	}
	for(int i=1;i<=n;i++)
	{
		int pre=find(i);
		if(ans[pre]!=-1)
		{
			ans[i]=ans[pre];
		}
		else
		{
			int now=0;
			unordered_map<int,bool>mp{};
			for(int j=1;j<=cnt1[pre];j++) mp[ans[dis[pre][j]]]=1;
			while(mp[now])++now;
			ans[i]=ans[pre]=now;
		}
	}
	for(int i=1;i<=n;i++) cout<<ans[i]<<" ";
	return 0;
}

B 忍者小隊

點選檢視程式碼
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=6e5+10,M=3e5;
int n,m,cnt[N],mn[N],mx[N],g[N];
int p[N],tot,vis[N],mu[N];
signed main()
{
    freopen("sor.in","r",stdin);
    freopen("sor.out","w",stdout);
    ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	mu[1]=1;
	for(int i=2;i<=M;i++)
	{
	    if(!vis[i]) p[++tot]=i,mu[i]=-1;
	    for(int j=1;j<=tot&&p[j]*i<=M;j++)
		{
	        vis[p[j]*i]=1;
	        if(i%p[j]==0) break;
	        mu[i*p[j]]=-mu[i];
	    }
	}
	cin>>n>>m;
	for(int i=1,x;i<=n;i++) cin>>x,cnt[x]++;
	memset(mn,0x3f,sizeof(mn));
	for(int i=1;i<=M;i++) for(int j=i;j<=M;j+=i) mx[i]+=cnt[j];
	for(int i=M;i;i--)
	{
	    if(cnt[i])
		{mn[i]=1;continue;}
	    for(int j=1;i*j<=M;j++) g[j]=0;
	    for(int j=1;i*j<=M;j++)
	    for(int k=j;i*k<=M;k+=j)
	         g[k]+=mx[i*j]*mu[j];
	    for(int j=2;i*j<=M;j++)
	        if(g[j]) mn[i]=min(mn[i],mn[i*j]+1);
	}
	for(int i=1;i<=m;i++)
	    if(mn[i]>1e9) cout<<"-1 -1\n";
	    else cout<<mn[i]<<" "<<mx[i]<<"\n";
    return 0;
}

C 狗卡

考慮怎麼最小。

結論是當選到第 \(i\) 個的某個連續序列,當且僅當這一段的平均數最小,每次扔到優先佇列裡頭搞就行。

然後第一個包用按 \(a\) 排序的優先佇列。

點選檢視程式碼
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=6e5+5;
int n,m;
int k[N],*a[N];
inline int read()
{
	register int s=0;
	register char c=getchar();
	while(c<'0'||c>'9') c=getchar();
	while(c>='0'&&c<='9') s=(s<<1)+(s<<3)+(c^48),c=getchar();
	return s;
}
int cnt[N];
struct node{
	double so;
	int i,l,r;
	bool operator<(const node&ll) const{
		return so>ll.so;
	}
};
priority_queue<node>q;
signed main()
{
	freopen("dog.in","r",stdin);
	freopen("dog.out","w",stdout);
	n=read(),m=read();
	bool _=1;
	for(int i=1;i<=n;i++)
	{
		k[i]=read();
		a[i]=new int [k[i]+2];
		int pos=0,sum=0;double mi=1e9;
		for(int j=1;j<=k[i];j++) 
		{
			a[i][j]=read();
			if(j>1) _&=(a[i][j]>=a[i][j-1]);
			sum+=a[i][j];
			if(sum<mi*j) mi=1.0*sum/j,pos=j;
		}
		q.push({mi,i,1,pos});
	}
	if(_)
	{
		priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > >q{};
		for(int i=1;i<=n;i++) q.push({a[i][1],i});
		int tim=0,now=0;
		int ans=0;
		while(!q.empty())
		{
			int pos=q.top().second;
			int val=q.top().first;
			q.pop();
			ans+=now*(val-1),tim+=val; 
			now++;ans+=now;
			if(cnt[pos]<k[pos]-1) q.push({a[pos][cnt[pos]+2],pos});
			cnt[pos]++;
		}
		ans=ans+(m-tim-1)*now;
		return cout<<ans,0;
	}
	int tim=0,v=0;
	int ans=0;
	while(!q.empty())
	{
		node now=q.top();
//		cout<<pos<<" "<<val<<"\n";
		q.pop();
		for(int i=now.l;i<=now.r;i++)
		{
			ans+=v*a[now.i][i];
			tim+=a[now.i][i];
			++v;
		}
		int pos=0,sum=0;double mi=1e9;
		for(int j=now.r+1;j<=k[now.i];j++) 
		{
			sum+=a[now.i][j];
			if(sum<mi*(j-now.r)) mi=1.0*sum/(j-now.r),pos=j;
		}
		if(now.r+1<=k[now.i])
		q.push({mi,now.i,now.r+1,pos});
	}
	ans=ans+(m-tim)*v;
	cout<<ans;
}

D 怪盜德基