题目链接:https://ac.nowcoder.com/acm/contest/893#rank
白天做题做的很自闭,晚上硬着头皮做了,还好都做出来了。
A:Who's better?
#include<bits/stdc++.h>
using namespace std;
int main()
{
int x1,x2,y1,y2,z1,z2;
cin>>x1>>y1>>z1>>x2>>y2>>z2;
if(x1>x2 || x1==x2&&y1<y2 || x1==x2&&y1==y2&&z1<z2) cout<<"1"<<endl;
else if(x1==x2&&y1==y2&&z1==z2)cout<<"God\n";
else cout<<"2"<<endl;
return 0;
}
B:Number
小模拟,不够除,就直接加到整除
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
int T;
cin>>T;
while(T--)
{
int n;
ll ans=0;
cin>>n;
int m;
while(n>1)
{
if(n%10==0) n=n/10,ans++;
else
{
m=n/10;
ans+=(m+1)*10-n;
n=(m+1)*10;
}
}
cout<<ans<<endl;
}
return 0;
}
C:Math Problem
才192,直接从l和r向右,向左枚举找到第一个符合的,在等差求和即可,当时傻逼了,二分求的
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
int T;
cin>>T;
while(T--)
{
int l,r;
cin>>l>>r;
ll al=-1,ar=-1;
ll l_=0,r_=1e9;
while(l_<=r_)
{
ll mid=(r_+l_)>>1;
if(mid*192+1>=l)
{
al=mid*192+1;
r_=mid-1;
}
else
{
l_=mid+1;
}
}
l_=0,r_=1e9;
while(l_<=r_)
{
ll mid=(r_+l_)>>1;
if(mid*192+1<=r)
{
ar=mid*192+1;
l_=mid+1;
}
else
{
r_=mid-1;
}
}
// cout<<al<<" "<<ar<<endl;
if(al>ar) cout<<"0\n";
else
{
cout<<(al+ar)*(ar-al+192)/192/2<<endl;
}
}
return 0;
}
D:Stone
思维,最大的去除,其他堆算一次即可
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
int T;
cin>>T;
while(T--)
{
int n;
cin>>n;
ll x,sum=0,maxx=0;
for(int i=1;i<=n;i++)
{
scanf("%lld",&x);
sum+=x;
maxx=max(x,maxx);
}
cout<<sum-maxx<<endl;
}
return 0;
}
E:Watermelon
我是先枚举lililalala前面的人吃掉了多少,剩下p,然后二分判断的,因为要满足p = k * lililalala的 + k * ([n-1, sum - lililalala] ),看是否能找到符合条件的k
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+10;
int n,m;
int a[N];
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
int id=1;
ll sum=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);sum+=a[i];
if(a[i]>a[id])
{
id=i;
}
}
if(n==1)
{
printf("YES\n");
continue;
}
sum-=a[id];
int cnt=0;
for(int i=1;i<id;i++)cnt+=a[i];
int flag=0;
if(cnt>=m && m>=id-1)
{
printf("YES\n");
continue;
}
if(m<id-1)
{
printf("NO\n");
continue;
}
double tmp,t;
for(int i=id-1;i<=cnt;i++)
{
tmp=m-i;
int l=1,r=tmp/a[id];
while(l<=r)
{
int mid=(r+l)>>1;
if(tmp/mid-a[id] < n-1)
{
r=mid-1;
}
else if(tmp/mid-a[id]>sum)
{
l=mid+1;
}
else
{
flag=1;
break;
}
}
if(flag) break;
}
printf(flag?"YES\n":"NO\n");
}
return 0;
}
F:Black & White
我是尺取做的,先把连续1和0的区间记录下来,然后用m取填补,最后有可能计算出来的超过了n,和n取个较小值即可
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
struct node{
int l,r;
}a[N],b[N];
int n,m;
int len;
char s[100100];
int main()
{
int T;
cin>>T;
while(T--)
{
scanf("%d%d",&n,&m);
scanf("%s",s+1);
len=0;
for(int i=1;i<=n;)
{
if(s[i]=='1')
{
len++;
b[len].l=i;
while(i<=n&&s[i]=='1') i++;
b[len].r=i-1;
}
else i++;
}
b[len+1].l=2000000000+10;
int ll=1,rr=2;
int nn=len;
int cnt=m;
int ans=0;
int maxx;
while(rr<=nn+1)
{
while(rr<=nn+1 && cnt>=0)
{
ans=max(ans,b[rr - 1].r - b[ll].l + 1 + cnt);
cnt-=b[rr].l-b[rr-1].r-1;
rr++;
}
cnt += b[ll+1].l - b[ll].r - 1;
ll++;
}
maxx=ans;
ans=0;
len=0;
for(int i=1;i<=n;)
{
if(s[i]=='0')
{
len++;
b[len].l=i;
while(i<=n&&s[i]=='0') i++;
b[len].r=i-1;
}
else i++;
}
b[len+1].l=2000000000+10;
ll=1,rr=2;
nn=len;
cnt=m;
while(rr<=nn+1)
{
while(rr<=nn+1 && cnt>=0)
{
ans=max(ans,b[rr - 1].r - b[ll].l + 1 + cnt);
cnt-=b[rr].l-b[rr-1].r-1;
rr++;
}
cnt += b[ll+1].l - b[ll].r - 1;
ll++;
}
maxx=max(maxx,ans);
maxx=min(maxx,n);
printf("%d\n",maxx);
}
return 0;
}
G:Truthman or Fakeman
若A说B为诚实的,那么 要么A和B都是诚实的,要么都不诚实
若A说B不诚实的,那么A和B,其中一个诚实,一个不诚实
所以A和B建边,每个独立集,有一个确定下来其他的就都确定了,枚举每个独立集中的一个,看他为诚实和不诚实的,取个该独立集得到诚实的人数较多的情况即可
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
struct node{
int to,nex;
bool p;
}e[N*2];
int n,m;
int vis[N];
int flag;
int head[N],len;
void add(int x,int y,bool z)
{
e[len].to=y;
e[len].p=z;
e[len].nex=head[x];
head[x]=len++;
}
int s1,s2;
void dfs(int u,int f)
{
for(int i=head[u];i!=-1;i=e[i].nex)
{
if(e[i].to==f) continue;
if(vis[e[i].to]!=-1)
{
if(e[i].p==1 && vis[u] != vis[e[i].to] ) flag=0;
if(e[i].p==0 && vis[u] == vis[e[i].to] ) flag=0;
continue;
}
if(e[i].p==1) vis[e[i].to]=vis[u];
else vis[e[i].to]=!vis[u];
if(vis[e[i].to]==1)s1++;else s2++;
dfs(e[i].to,u);
if(!flag)
{
vis[e[i].to]=-1;
return;
}
}
}
void dfs1(int u,int f)
{
vis[u]=-1;
for(int i=head[u];i!=-1;i=e[i].nex)
{
if(e[i].to==f) continue;
if(vis[e[i].to]==-1) continue;
dfs1(e[i].to,u);
}
}
int main()
{
int T;
int x,y;
int z;
cin>>T;
while(T--)
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
head[i]=-1;
vis[i]=-1;
}
len=0;
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&x,&y,&z);
add(x,y,z);
add(y,x,z);
}
flag=1;
for(int i=1;i<=n;i++)
{
flag=1;
if(vis[i]!=-1) continue;
vis[i]=1;
s1=0,s2=0;
s1++;
dfs(i,0);
if(!flag)
{
flag=1;
vis[i]=0;
dfs(i,0);
if(!flag) break;
}
else
{
int maxx=s1-s2;
s1=0,s2=0;
dfs1(i,0);
flag=1;
vis[i]=0;
s2++;
dfs(i,0);
// cout<<maxx<<" "<<s1<<" "<<s2<<endl;
if(flag)
{
if(s1-s2<maxx)
{
dfs1(i,0);
vis[i]=1;
dfs(i,0);
}
}
}
}
if(flag==0) printf("-1\n");
else
{
for(int i=1;i<=n;i++)
{
printf("%d",vis[i]);
}
printf("\n");
}
}
return 0;
}
H:Chat
预处理+分组背包
我是先把m为0时的情况算出来,就是每天最右1-最左1的和,然后把每天让女生生气k次,减少的时间最多的情况算出来,因为每天选的区间只有一个,所以让女生生气也只是左连续和右连续,最后求个让女生生气k次,得到最大的时间,因为每一天只能确定一个,所以是个分组背包
#include<bits/stdc++.h>
using namespace std;
char s[210];
int dp[210][210];
struct node{
int w,v;
}a[210][210];
int len[210];
int n,m,k;
int l[210],r[210];
int cmp(const node &xx,const node &yy)
{
return xx.w<yy.w;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int sum=0;
int ll,rr;
int flag,cnt;
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=n;i++)
{
scanf("%s",s+1);
len[i]=0;
ll=m+1,rr=0;
flag=0;
cnt=0;
for(int j=1;j<=m;j++)
{
if(s[j]=='1')
{
if(flag)
{
l[flag]=cnt;
// cout<<flag<<" "<<cnt<<endl;
}
ll=min(ll,j),rr=max(rr,j),flag++;
}
if(flag) cnt++;
}
if(flag) l[flag]=rr-ll+1,sum+=rr-ll+1;
else continue;
flag=0;
cnt=0;
for(int j=m;j>=1;j--)
{
if(s[j]=='1')
{
if(flag)
{
r[flag]=cnt;
// cout<<flag<<" "<<cnt<<endl;
}
flag++;
}
if(flag) cnt++;
}
r[flag]=rr-ll+1;
if(flag)
{
for(int j=1;j<flag;j++)
{
cnt=0;
for(int k=0;k<=j;k++)
{
// cout<<k<<" "<<l[k]<<" * "<<r[j-k]<<endl;
cnt=max(cnt,l[k]+r[j-k]);
}
// cout<<j<<" "<<cnt<<endl;
a[i][++len[i]].w=j;
a[i][len[i]].v=cnt;
}
a[i][++len[i]].w=flag;
a[i][len[i]].v=rr-ll+1;
}
sort(a[i]+1,a[i]+1+len[i],cmp);
}
memset(dp,0,sizeof(dp));
// sort(a+1,a+1+len,cmp);
for(int i=1;i<=n;i++)
{
for(int kk=k;kk>=0;kk--)
{
dp[i][kk]=dp[i-1][kk];
for(int j=1;j<=len[i];j++)
{
if(a[i][j].w>kk) break;
dp[i][kk]=max(dp[i][kk],dp[i-1][kk-a[i][j].w]+a[i][j].v);
}
}
}
// cout<<sum<<" "<<dp[n][k]<<endl;
printf("%d\n",sum-dp[n][k]);
}
return 0;
}