省选模拟44
天天天天的挂大分!!!今天T1挂50,原因少判一个条件...
说实话今天的题怪没意思的,俩构造一交互,主要是数据范围迷到死
T1 构树
平方枚举直接连边
AC_code
#include<bits/stdc++.h>
using namespace std;
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
int read(){
int s=0,t=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')t=-1;ch=getchar();}
while(isdigit(ch)){s=(s<<1)+(s<<3)+(ch^48);ch=getchar();}
return s*t;
}
const int N=1005;
int n,a[N],b[N],can;
bool ban;
pair<int,int> ans[N];
int fai[N];
int find(int x){return fai[x]==x?x:fai[x]=find(fai[x]);}
signed main(){
freopen("tree.in","r",stdin);
freopen("tree.out","w",stdout);
n=read();
fo(i,1,n)fai[i]=i;
fo(i,1,n){
a[i]=read();b[i]=read();
int fx=find(i),fy=find(a[i]);
if(fx==fy&&a[a[i]]!=i&&b[a[i]]!=i)ban=true;
else if(fx!=fy)fai[fx]=fy,ans[++can]=make_pair(a[i],i);
if(a[i]==b[i])continue;
fx=find(i);fy=find(b[i]);
if(fx==fy&&a[b[i]]!=i&&b[b[i]]!=i)ban=true;
else if(fx!=fy)fai[fx]=fy,ans[++can]=make_pair(b[i],i);
}
if(ban){printf("-1");return 0;}
fo(i,1,n){
fo(j,a[i]+1,b[i]-1){
if(i<a[j]||i>b[j])continue;
int fx=find(i),fy=find(j);
if(fx==fy)continue;
fai[fx]=fy;
ans[++can]=make_pair(i,j);
}
}
if(can==n-1){
fo(i,1,n-1)printf("%d %d\n",ans[i].first,ans[i].second);
}
else printf("-1");
return 0;
}
T2 交互
单调栈,考试的时候想到了,但是后来因为看错题了就不想这方面了,一开始看成了包含就返回true
由于这个树的特殊性,小于一个点的一定在这个点的左子树或者父亲
所以我们从小到大加入点,一旦子树满了,我们就弹出然后连边。。。
AC_code
#include<bits/stdc++.h>
#include"interact.h"
using namespace std;
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
int read(){
int s=0,t=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')t=-1;ch=getchar();}
while(isdigit(ch)){s=(s<<1)+(s<<3)+(ch^48);ch=getchar();}
return s*t;
}
const int N=105;
int sta[N],top,l[N],r[N];
void guess(int n){
if(n==1)return ;
fo(i,1,n){
int las=0;
while(top&&query(sta[top],l[sta[top]],r[sta[top]])){
if(las){
report(sta[top],las);
}
las=sta[top];top--;
if(top)r[sta[top]]=r[sta[top+1]];
}
l[i]=i;r[i]=i;
if(las){
report(i,las);
l[i]=l[las];r[i]=i;
}
sta[++top]=i;
}
fo(i,1,top-1)report(sta[i],sta[i+1]);
}
T3 构图
平方暴力做,枚举有几个恰好k度的点,我考场上直接贪心了,假了
AC_code
#include<bits/stdc++.h>
using namespace std;
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
int read(){
int s=0,t=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')t=-1;ch=getchar();}
while(isdigit(ch)){s=(s<<1)+(s<<3)+(ch^48);ch=getchar();}
return s*t;
}
const int N=1005;
int n,k,ans;
int g[N],h[N],f[N],sta[N],top;
int pre[N],ok[N],ned[N];
pair<int,int> res[N*N];
priority_queue<pair<int,int>> q;
signed main(){
freopen("graph.in","r",stdin);
freopen("graph.out","w",stdout);
n=read();k=read();
fo(i,k+2,n){
int res;g[i]=0x3f3f3f3f;
fo(j,1,i-k){
if(j*k/(i-j)>=k+1)res=j*k;
else res=j*k+((k+1-j*k/(i-j))*(i-j)-j*k%(i-j)-1)/2+1;
// cerr<<i<<" "<<j<<" "<<res<<endl;
if(res<g[i])g[i]=res,h[i]=j;
}
}
memset(f,0x3f,sizeof(f));f[0]=0;
fo(i,k+2,n)fo(j,0,i-k-2){
if(f[i]>f[j]+g[i-j]){
f[i]=f[j]+g[i-j];
pre[i]=j;
}
}
printf("%d\n",f[n]);
int now=n;
while(now){
// cerr<<now<<" "<<pre[now]<<endl;
int det=now-pre[now];
// cerr<<h[det]<<endl;
int sum=det-h[det],tmp=1,al=0;
fo(i,1,h[det]){
fo(j,1,k){
res[++ans]=make_pair(i+pre[now],tmp+pre[now]+h[det]);
tmp++;if(tmp>sum)tmp=1,al++;
}
}
// cerr<<"SB"<<endl;
ok[0]=tmp-1;
fo(i,1,sum){
ok[i]=ok[i-1]+1;
if(ok[i]>sum)ok[i]=1;
}
int cha=1;
fo(i,1,sum){
if(ok[i]==1)al++;
ned[ok[i]]=k+1-al;
q.push(make_pair(ned[ok[i]],ok[i]));
}
while(!q.empty()){
pair<int,int> x=q.top();q.pop();
// cerr<<x.first<<endl;
int sum=x.first;top=0;
while(!q.empty()&&sum>0){
res[++ans]=make_pair(x.second+pre[now]+h[det],q.top().second+pre[now]+h[det]);
sta[++top]=q.top().second;ned[q.top().second]--;sum--;q.pop();
}
if(sum>0){
fo(i,1,sum)res[++ans]=make_pair(x.second+pre[now]+h[det],i+pre[now]);
}
fo(i,1,top)if(ned[sta[i]])q.push(make_pair(ned[sta[i]],sta[i]));
}
now=pre[now];
}
fo(i,1,ans)printf("%d %d\n",res[i].first,res[i].second);
return 0;
}
QQ:2953174821