清北刷题冲刺 10-29 p.m
洗澡
/* 这个题不能单纯判断左括号和右括号的多少,而应该从左到右扫一遍,看应该如何配对 */ #include<iostream> #include<cstdio> #include<cstring> using namespace std; char s[100010]; int cnt,ans; int main(){ freopen("bracket.in","r",stdin);freopen("bracket.out","w",stdout); //freopen("Cola.txt","r",stdin); scanf("%s",s+1); int len=strlen(s+1); for(int i=1;i<=len;i++){ if(s[i]==')'){ if(cnt==0)cnt++,ans++; else cnt--; } else cnt++; } ans+=cnt/2; cout<<ans; }
日记
#include<iostream> #include<cstdio> #include<cstring> #include<ctime> #define maxn 2010 #ifdef WIN32 #define PLL "%I64d" #else #define PLL "%lld" #endif using namespace std; int T; struct node{ int n,k; }a[maxn]; bool flag=1,vis[1000010]; int p[80000],cnt,mx; long long sum[80000]; void prepare(){ for(int i=2;i<=mx;i++){ if(!vis[i])vis[i]=1,p[++cnt]=i; for(int j=1;j<=cnt&&i*p[j]<=mx;j++){ vis[i*p[j]]=1; if(i%p[j]==0)break; } } for(int i=1;i<=cnt;i++)sum[i]=sum[i-1]+p[i]; } int find(int x){//寻找不超过x的最大的数的位置 int l=1,r=cnt,res=-1; while(l<=r){ int mid=(l+r)>>1; if(p[mid]<=x)res=mid,l=mid+1; else r=mid-1; } return res; } int find2(int l,int r,int x,int k){//寻找结尾为l~r的,区间长度为k的,不超过x的最大的数的结尾位置 int res=-1; while(l<=r){ int mid=(l+r)>>1; if(sum[mid]-sum[mid-k]<=(long long)x)res=mid,l=mid+1; else r=mid-1; } return res; } int main(){ freopen("diary.in","r",stdin);freopen("diary.out","w",stdout); // freopen("Cola.txt","r",stdin); scanf("%d",&T); for(int i=1;i<=T;i++){ scanf("%d%d",&a[i].n,&a[i].k); if(i!=1&&a[i].n!=a[i-1].n)flag=0; mx=max(mx,a[i].n); } prepare(); if(flag){ int pos=find(a[1].n);//寻找小于等于n的最大的数 if(pos==-1){ for(int i=1;i<=T;i++)puts("-1"); return 0; } for(int i=1;i<=T;i++){ if(a[i].k>pos||sum[a[i].k]>a[i].n){puts("-1");continue;} int posnow=find2(a[i].k,pos,a[i].n,a[i].k); if(posnow==-1){puts("-1");continue;} long long now=sum[posnow]-sum[posnow-a[i].k]; printf(PLL"\n",now); } return 0; } for(int i=1;i<=T;i++){ int pos=find(a[i].n); if(pos==-1){puts("-1");continue;} if(a[i].k>pos||sum[a[i].k]>a[i].n){puts("-1");continue;} int posnow=find2(a[i].k,pos,a[i].n,a[i].k); if(posnow==-1){puts("-1");continue;} long long now=sum[posnow]-sum[posnow-a[i].k]; printf(PLL"\n",now); } return 0; }
洗衣
/* 对每个树暴力建图,map[i][j][k]表示第i棵树的j与k之间的距离 对于每棵树,先暴力经行边权赋值(根据a树和b树以及l),再跑一遍floyed,最后统计答案即可 */ #include<iostream> #include<cstdio> #include<cstring> using namespace std; int map[21][1025][1025]; int sz[61]; int m,a,b,c,d,l; void fl(int x){ for(int k=0;k<sz[x];k++) for(int i=0;i<sz[x];i++) for(int j=0;j<sz[x];j++){ if(i==j||i==k||j==k)continue; map[x][i][j]=min(map[x][i][j],map[x][i][k]+map[x][k][j]); } int ans=0; for(int i=0;i<sz[x];i++) for(int j=i+1;j<sz[x];j++) ans+=map[x][i][j]; printf("%d\n",ans); } int main(){ freopen("cloth.in","r",stdin);freopen("cloth.out","w",stdout); // freopen("Cola.txt","r",stdin); memset(map,0x3f,sizeof(map)); sz[0]=1;map[0][0][0]=0; scanf("%d",&m); for(int i=1;i<=m;i++){ scanf("%d%d%d%d%d",&a,&b,&c,&d,&l); sz[i]=sz[a]+sz[b]; for(int j=0;j<sz[a];j++) for(int k=j;k<sz[a];k++) map[i][j][k]=map[i][k][j]=map[a][j][k]; for(int j=0;j<sz[b];j++) for(int k=j;k<sz[b];k++) map[i][j+sz[a]][k+sz[a]]=map[i][k+sz[a]][j+sz[a]]=map[b][j][k]; map[i][c][d+sz[a]]=map[i][d+sz[a]][c]=l; fl(i); } return 0; }
预计得分100+100+30 实际得分100+100+40 T1是个比较简单的模拟,T2两次二分查找,前两道题都比较好想,代码已不太容易出错 T3完全没有思路,在想怎么存图,想到可以给数组增加一个维度,这样应该可以过前30%的数据,就这么做了 这次考试比上午简单一点,暴力分拿到了,也没有犯很低级的错误