Loading

noip模拟57

A. 2A

签到题.

A_code
#include<bits/stdc++.h>
using namespace std;
namespace BSS {
	#define ll long long int
	#define ull unsigned ll
	#define lf double
	#define lbt(x) (x&(-x))
	#define mp(x,y) make_pair(x,y)
	#define lb lower_bound 
	#define ub upper_bound
	#define Fill(x,y) memset(x,y,sizeof x)
	#define Copy(x,y) memcpy(x,y,sizeof x)
	#define File(x,y) freopen(#x,"r",stdin),freopen(#y,"w",stdout)
	#define FILE(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout)
	inline ll read() {
		int ss=0; bool cit=1; char ch;
		while(!isdigit(ch=getchar())) if(ch=='-') cit=0; 
		while(isdigit(ch)) ss=(ss<<3)+(ss<<1)+(ch^48),ch=getchar();
		return cit?ss:-ss;
	}
} using namespace BSS;

char s[201];

ll m,n,flag;
ll ans[201]	;
inline void Match(){
	ll i=1,j=1,k;
	if(!isdigit(s[i])) flag=0;
	while(i<=n){
		if(isdigit(s[i])){
			if(isdigit(s[i+1]) and s[i]=='0') flag=0;
			while(isdigit(s[i]) and i<=n){
				ans[j]=(ans[j]<<3)+(ans[j]<<1)+(s[i]^48);
				i++;
			}
			flag&=(ans[j]<=255),j++;
		}
		else{
			k=0;
			while((!isdigit(s[i])) and i<=n){
				i++,k++;
			}
			if(!(k==1 and s[i-1]=='.')) flag=0;
			if(j>4 or j==1) flag=0;
		}
	}
	flag&=(j==5);
}
signed main(){
	FILE(ip);
	scanf("%s",s+1),n=strlen(s+1),flag=1,Match();
	if(flag) puts("YES");
	else{
		puts("NO");
		for(int i=1;i<=3;i++){
			printf("%lld.",ans[i]>255 ? 255 : ans[i]);
		}
		printf("%lld",ans[4]>255 ? 255 : ans[4]);
	}
	exit(0);
}

B. 2B

签到题.

B_code
#include<bits/stdc++.h>
using namespace std;
namespace BSS {
	#define ll long long int
	#define ull unsigned ll
	#define lf double
	#define lbt(x) (x&(-x))
	#define mp(x,y) make_pair(x,y)
	#define lb lower_bound 
	#define ub upper_bound
	#define Fill(x,y) memset(x,y,sizeof x)
	#define Copy(x,y) memcpy(x,y,sizeof x)
	#define File(x,y) freopen(#x,"r",stdin),freopen(#y,"w",stdout)
	#define FILE(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout)
	inline ll read() {
		int ss=0; bool cit=1; char ch;
		while(!isdigit(ch=getchar())) if(ch=='-') cit=0; 
		while(isdigit(ch)) ss=(ss<<3)+(ss<<1)+(ch^48),ch=getchar();
		return cit?ss:-ss;
	}
} using namespace BSS;

const ll N=1e4+21;

char s[N];

ll m,n,as,ps;
ll c[N];
signed main(){
	FILE(apstr);
	scanf("%s",s+1),n=strlen(s+1);
	for(int i=1;i<=n;i++) c[i]=(s[i]=='A' ? 1 : 2);
	for(int i=n;i>=1;i--){
		if(c[i]&1) as+=(ps<=0),ps-=(ps>0);
		else ps++;
	}
	printf("%lld\n",as+(ps&1));
	exit(0);
}

C. 2C

读不懂题,枯了.
复杂度 \(O(\dfrac{n^2logn}{32})\).

C_code
#include<bits/stdc++.h>
using namespace std;
namespace BSS {
	#define ll long long
	#define ull unsigned ll
	#define lf double
	#define lbt(x) (x&(-x))
	#define mp(x,y) make_pair(x,y)
	#define lb lower_bound 
	#define ub upper_bound
	#define Fill(x,y) memset(x,y,sizeof x)
	#define Copy(x,y) memcpy(x,y,sizeof x)
	#define File(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout)
	inline ll read() {
		ll res=0; bool cit=1; char ch;
		while(!isdigit(ch=getchar())) if(ch=='-') cit=0; 
		while(isdigit(ch)) res=(res<<3)+(res<<1)+(ch^48),ch=getchar();
		return cit?res:-res;
	}
} using namespace BSS;

const ll N=1005;

ll m,n,ops,tot;
ll bin[N];
unordered_map<string,ll> vis;
bitset<N> R[N],Now;
signed main(){ 
	File(class);
	ops=read(); char s[15],t[15]; ll cnt,flag;
	while(ops--){
		scanf("%s",t+1),cnt=0,flag=1,scanf("%s",s+1);
		if(vis.find(t+1)!=vis.end()) flag=0;
		while(scanf("%s",s+1),s[1]!=';'){
			if(vis.find(s+1)==vis.end()) flag=0;
			else bin[++cnt]=vis[s+1];
		}
		if(not flag) { puts("greska"); continue; }
		sort(bin+1,bin+1+cnt,[](ll i,ll j){ return i>j; });
		Now.reset();
		for(int i=1;i<=cnt;i++){
			if(Now[bin[i]]) continue; 
			if((Now&R[bin[i]])!=0) { flag=0; break; }
			Now|=R[bin[i]];
		}
		if(not flag) { puts("greska"); continue; }
		vis[t+1]=++tot,R[tot].set(tot,1);
		for(int i=1;i<=cnt;i++) R[tot]|=R[bin[i]];
		puts("ok");
	}
	exit(0);
}
/*
10
a : ;
c : a ;
b : a ;
b : ;
d : a c ;
f : e ;
e : ;
f : e a ;
g : f ;
h : d g ;
*/	

D. 2D

在思考过程中应该可以想到'开拓'的思路.

考虑如何去开拓,也就是考虑如何去更新 \(m、n\)\(b\).

发现每个点对于已有的块来说造成的影响与 ta 和块的连边.

所以一个神奇的思路就是观察每个点最多能在 \(K\) 等于几的块中.

给每个点打一个标记,然后从标记大的向标记小的开拓.

在开拓过程中更新答案即可.

一个点无论位于什么图中,ta 的 \(K\) 一定是小于等于 ta 的度数的.

并且这个 \(K\) 如果想要取等,那么 ta 的所有边连接的点都是度数比 ta 自己大的点.

因为在连接比整个图的最小度数都不大的点时,一定不会让自己当前位于的图的 \(K\) 变大.

所以我们考虑时只需要考虑自己连向的度数大的点即可.

每连向一个度数小的点就让自己的度数减 \(1\).

可以使用 \(vector\) 类拓扑排序来完成 (做法来自沈队).

复杂度为 \(O(n)\)\(O(nlogn)\),瓶颈在于并查集.

D_code
#include<bits/stdc++.h>
using namespace std;
namespace BSS {
	#define ll long long int
	#define ull unsigned ll
	#define lf long double
	#define lbt(x) (x&(-x))
	#define mp(x,y) make_pair(x,y)
	#define lb lower_bound
	#define ub upper_bound
	#define Fill(x,y) memset(x,y,sizeof x)
	#define Copy(x,y) memcpy(x,y,sizeof x)
	#define File(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout)
	inline ll read() {
		ll res=0; bool cit=1; char ch;
		while(!isdigit(ch=getchar())) if(ch=='-') cit=0; 
		while(isdigit(ch)) res=(res<<3)+(res<<1)+(ch^48),ch=getchar();
		return cit?res:-res;
	}
} using namespace BSS;

const ll N=1e6+21,inf=1e18;

ll m,n,xm,xn,xb,ansk,ansc,ts,maxk;
ll d[N],rk[N],le[N],ge[N],fa[N],head[N];
vector<ll> bin[N];
struct I { ll u,v,nxt; } e[N<<1];
struct II { ll n,m,b; } p[N];
inline void add(ll u,ll v){
	e[++ts].u=u,e[ts].v=v,e[ts].nxt=head[u];
	head[u]=ts,d[u]++;
}
inline ll find(ll x){ return fa[x]==x ? x : fa[x]=find(fa[x]); }
inline void unit(ll x,ll y){
	ll fx=find(x),fy=find(y);
	if(fx==fy) return ;
	fa[fx]=fy,p[fy].m+=p[fx].m,p[fy].n+=p[fx].n,p[fy].b+=p[fx].b;
}
inline void calc(ll x,ll k){
	// cout<<x<<' '<<k<<' '<<p[x].m<<' '<<p[x].n<<' '<<p[x].b<<endl;
	ll res=xm*p[x].m-xn*p[x].n+xb*p[x].b;
	if(res>ansc or (res==ansc and ansk<k)) ansc=res,ansk=k;
}
signed main(){
	File(kdgraph);
	n=read(),m=read(),xm=read(),xn=read(),xb=read(),ansk=-inf,ansc=-inf; ll u,v,dad;
	for(int i=1;i<=m;i++){
		u=read(),v=read(),add(u,v),add(v,u);
	}
	for(int i=1;i<=n;i++) bin[d[i]].push_back(i);
	for(int i=1;i<=n;i++){
		for(int j=0;j<bin[i].size();j++){
			u=bin[i][j];
			if(rk[u]) continue; rk[u]=i;
			for(int k=head[u];k;k=e[k].nxt)
				v=e[k].v,d[v]--,bin[d[v]].push_back(v);
		}
	}
	for(int i=0;i<=n;i++) bin[i].clear();
	for(int i=1;i<=n;i++) bin[rk[i]].push_back(i),maxk=max(maxk,rk[i]),fa[i]=i;
	// for(int i=1;i<=n;i++) cout<<rk[i]<<' '; puts("");
	for(u=1;u<=n;u++){
		for(int i=head[u],v=e[i].v;i;i=e[i].nxt,v=e[i].v){
			le[u]+=(rk[u]<rk[v] or (rk[u]==rk[v] and u>v));
			ge[u]+=(rk[u]>rk[v] or (rk[u]==rk[v] and u>v));
		}
	}
	// for(int i=1;i<=n;i++) cout<<le[i]<<' '<<ge[i]<<endl;
	for(int i=maxk;i>=1;i--){
		for(auto j : bin[i]){
			for(int k=head[j];k;k=e[k].nxt)
				if(rk[e[k].v]>=rk[j]) unit(j,e[k].v);
			dad=find(j),p[dad].n++,p[dad].m+=le[j],p[dad].b+=ge[j]-le[j];
		}
		for(auto j : bin[i]) calc(find(j),i);
	}
	printf("%lld %lld\n",ansk,ansc),exit(0);
}
posted @ 2021-09-22 20:14  AaMuXiiiiii  阅读(35)  评论(0编辑  收藏  举报