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);
}