2021.06.06模拟赛

写在前面:生成树yyds!
题面

T1 种胡萝卜

坑太多暴力过不去!
用并查集!啪的一下就输出了!很快啊!
code:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define maxn 3000010
#define ll long long
using namespace std;
template<typename T>
inline void read(T &x){
	x=0;bool flag=0;char c=getchar();
	for(;!isdigit(c);c=getchar()) if(c=='-') flag=1;
	for(;isdigit(c);c=getchar()) x=x*10+(c^48);
	if(flag) x=-x;
}

const int mod=1000000007;
ll n,m,a,fa[maxn],ans;
bool flag[maxn];

int f(int x){
	return fa[x]=(fa[x]==x)?x:f(fa[x]);
}

int main(){
	read(n),read(m);
	for(int i=0;i<=m;i++) fa[i]=i;
	for(int i=1;i<=n;i++){
		read(a);
		ll fa1=f(a);
		if(!fa1) continue;
		ll fa2=f(fa1-1);
		(ans+=i*fa1)%=mod;
		if(fa1!=fa2) fa[fa1]=fa2;
	} 
	printf("%lld
",ans);
	return 0;
}
/*
5 8
7 7 1 6 1
*/
//42
/*
8 8
8 8 5 5 5 6 2 1
*/
//126

T2 sequence

贪心
数据范围很小啊 按右端点排排序然后暴力打flag,最后数数一共多少个flag就行了
code:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define maxn 1010
using namespace std;
template<typename T>
inline void read(T &x){
	x=0;bool flag=0;char c=getchar();
	for(;!isdigit(c);c=getchar()) if(c=='-') flag=1;
	for(;isdigit(c);c=getchar()) x=x*10+(c^48);
	if(flag) x=-x;
}

int n,c[maxn];
int ans,sum,ll=10010,rr=-1;
bool flag[maxn];
struct data{
	int l,r,c;
	bool friend operator < (data a,data b){
		if(a.r!=b.r) return a.r<b.r;
		return a.l<b.l;
	}
}s[maxn];

int main(){
	read(n);
	for(int i=1;i<=n;i++){
		read(s[i].l),read(s[i].r),read(s[i].c);
		ll=min(ll,s[i].l),rr=max(rr,s[i].r);
	}
//	cout<<ll<<" "<<rr<<"*"<<endl;
	sort(s+1,s+n+1);
//	for(int i=1;i<=n;i++) cout<<s[i].l<<" "<<s[i].r<<endl;
	for(int i=1;i<=n;i++){
		sum=0;
		for(int j=s[i].r;j>=s[i].l;j--){
			if(flag[j]) sum++;
		}
		if(sum>=s[i].c) continue;
		for(int j=s[i].r;j>=s[i].l;j--){
			if(sum==s[i].c) break;
			if(!flag[j]){
				flag[j]=1;
			    sum++;
			}
		}
	}
	for(int i=ll;i<=rr;i++) if(flag[i]) ans++;
	cout<<ans<<endl;
	return 0;
}
/*
4 
4 5 1 
6 10 3 
7 10 3 
5 6 1
*/
//4
/*
4
4 5 2
5 6 2
6 10 5
7 10 4
*///7

T3 最小代价

听说有神仙把它看成最大代价了
至于做法,其实也就是横纵坐标分别排排序,然后跑最小生成树宛如板子但是考场上愣是没做出来
还有, pii 真好用!
code:

#include<iostream>
#include<cstdio>
#include<algorithm>
#define ll long long
#define pii pair<int,int>
#define fir first
#define sec second
#define maxn 200010
using namespace std;
template<typename T>
inline void read(T &x){
	x=0; bool flag=0; char c=getchar();
	for(;!isdigit(c);c=getchar()) if(c=='-') flag=1;
	for(;isdigit(c);c=getchar()) x=x*10+(c^48);
	if(flag) x=-x;
}

int n,m;
int siz[maxn],fa[maxn];
int sum=0,cnt=0;
pii x[maxn],y[maxn];

struct bcj{
	void init(int n){
		for(int i=1;i<=n;i++) fa[i]=i,siz[i]=1;
	}
	int f(int x){
		return (fa[x]==x)?x:fa[x]=f(fa[x]);
	}
	void u(int x,int y,int z){//********
		x=f(x);y=f(y);
		if(x!=y){
			fa[x]=y;
			sum+=z;
			siz[y]+=siz[x];
		}
//		if(x==y) return false;
//		fa[x]=y;
//		return true;
	}
}s;

bool cmp (pii x,pii y){
	return x.sec<y.sec;
}

struct edge{
	int u,v,w;
	bool friend operator < (edge a,edge b){
		return a.w<b.w;
	}
}e[maxn];

int main(){
	read(n);
	s.init(n);
	for(int i=1;i<=n;i++) {
		read(x[i].sec);read(y[i].sec);
		x[i].fir=i,y[i].fir=i;
	}
	sort(x+1,x+n+1,cmp);
	sort(y+1,y+n+1,cmp);
	for(int i=1;i<=n-1;i++){
		m++;
		e[m].u=x[i].fir,e[m].v=x[i+1].fir,e[m].w=x[i+1].sec-x[i].sec;
		m++;
		e[m].u=y[i].fir,e[m].v=y[i+1].fir,e[m].w=y[i+1].sec-y[i].sec;
	}
	sort(e+1,e+m+1);
	for(int i=1;i<=m;i++){
//		if(s.u(e[i].u,e[i].v)){
//			sum+=e[i].w;
//			siz[s.f(e[i].v)]+=siz[s.f(e[i].u)];//****????
//		}
		s.u(e[i].u,e[i].v,e[i].w);
		int fax=s.f(e[i].u),fay=s.f(fa[e[i].v]);
		if(siz[fax]==n||siz[fay]==n){
			cout<<sum<<endl;
			break;
		}
	}
	return 0;
}
/*
3
1 5
3 9
7 8
*/
//3
原文地址:https://www.cnblogs.com/DReamLion/p/14859815.html