2016 PSUT Coding Marathon A~G
文章目录
A.LCS (A)
输出比输入多1
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n;
cin>>n;
cout<<n+1;
return 0;
}
B.LCS (B)
给c出一个DP矩阵,以及算法(求lcs),然后根据这个矩阵让你倒过来算出两个符合条件的原先的字符串。
显然要求lcs第一个字符串起到类似参照的作用,最后决定dp矩阵的数值大小的关键在于第二个字符串和第一个字符串的匹配程度。
因此考虑在状态转移中的条件,
if A[i] = B[j] DP[i,j] := DP[i-1,j-1] + 1
else DP[i,j] := max(DP[i,j-1], DP[i-1,j])
也就是说当DP[i,j]>max(DP[i,j-1], DP[i-1,j])的时候说明是从状态1(更优)转移过来的,这个时候说明这两个地方是同一种字母。多个集合指向同一种东西,想到用并查集。
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
inline long long read()
{
long long kk=0,f=1;
char cc=getchar();
while(cc<'0'||cc>'9'){if(cc=='-')f=-1;cc=getchar();}
while(cc>='0'&&cc<='9'){kk=(kk<<1)+(kk<<3)+cc-'0';cc=getchar();}
return kk*f;
}
int dp[30][30];
string ss,s1;
char a[30],b[30];
int fa[60];
int find(int x)
{
if(x==fa[x])return x;
return fa[x]=find(fa[x]);
}
void merge(int a,int b)
{
int aa=find(a),bb=find(b);
fa[bb]=aa;find(b);
}
int main()
{
int n=read(),m=read();
for(int i=0;i<58;++i)fa[i]=i;
for(int i=0;i<=n;++i)for(int j=0;j<=m;++j)
{
dp[i][j]=read();
if(dp[i][j]>max(dp[i-1][j],dp[i][j-1]))
{
merge(i-1,j-1+n);
}
}
for(int i=0;i<n;++i)a[i]=find(i)+'a';
for(int i=0;i<m;++i)
{
int lin=find(i+n);
if(lin==i+n)lin=25;
b[i]=lin+'a';
}
cout<<a<<endl<<b;
}
C.1D Cafeteria (A)
题意 给出每张桌子座位数和已使用的座位数,求未占用的座位数.
算法 模拟
#include<bits/stdc++.h>
using namespace std;
int main()
{
int t,a,b,s=0;
cin>>t;
while(t--)
{
cin>>a>>b;
s=s+b-a;
}
cout<<s;
}
D.Cafeteria (B)
题意 有N张容量已知的桌子,对于Q组来客与离客的操作,为来客分配落座的桌子,若没有合适的桌子,输出-1.
算法 模拟
解题 用set<pair<int,int>>来储存目前剩余的桌子即可.
#include<bits/stdc++.h>
using namespace std;
int a[100001],n,q,nu;
string str;
set<pair<int,int> > s;
set<pair<int,int> > ::iterator it;
int main()
{
cin>>n>>q;
for(int i=1;i<=n;i++)
{
cin>>a[i];
s.insert(make_pair(a[i],i));
}
while(q--)
{
cin>>str>>nu;
if(str[0]=='i') {
it=s.lower_bound(make_pair(nu,0));
if(it==s.end()) cout<<"-1"<<endl;
else
{
cout<<it->second<<endl;
s.erase(it);
}
}
else s.insert(make_pair(a[nu],nu));
}
}
E.Accepted Passwords
输入两串字符串,第一串是真密码,第二串是输入的密码。
一样的就是yes。
对于8位密码以上的可以错一位,或者漏一位
#include<bits/stdc++.h>
using namespace std;
int main()
{
int f=0;
char a[1000],b[1000];
cin>>a>>b;
if(strcmp(a,b)==0) cout<<"yes";
else if(strlen(a)<8) cout<<"no";
else {
if(strlen(b)==strlen(a)){
for(int i=0;i<strlen(b);i++)
{
if (a[i]!=b[i]){
if (f) {
cout<<"no";
return 0;
}
f=1;
}
}
cout<<"yes";
}
else
{
if (strlen(a)==strlen(b)+1)
{
for(int i=0;i<strlen(b);i++)
{
if(a[i+f]!=b[i])
if(f||a[i+1]!=b[i]){
cout<<"no";
return 0;
}
else f=1;
}
cout<<"yes";
}
else cout<<"no";
}
}
return 0;
}
F.Mission in Amman (A)
题意 给出初始位置已知的N人,进行Q次操作,求每一次操作过后M个场地中没人的场地的数量.
算法 模拟
#include<bits/stdc++.h>
using namespace std;
int a[100001],b[100001]={0},n,m,q,s=0,x,y;
int main()
{
cin>>n>>m>>q;
for(int i=1;i<=n;i++)
{
cin>>a[i];
b[a[i]]++;
}
for(int i=1;i<=m;i++)
if (b[i]==0) s++;
while(q--)
{
cin>>x>>y;
//cout<<a[1]<<' ';
if(b[a[x]]==1) s++;
if(b[y]==0) s--;
b[a[x]]--; b[y]++; a[x]=y;
cout<<s<<endl;
}
return 0;
}
G.Mission in Amman (B)
输入m个数,可以移动k次每一次可以从任意一个数里面减一其他的某个数加一
要让最后的最大值最小,求这个最大值
显然,根据k的值判断是否可行,二分答案。最理想的情况是答案是平均值(向上取整),最坏的情况就是现存的最大值。
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
inline long long read()
{
long long kk=0,f=1;
char cc=getchar();
while(cc<'0'||cc>'9'){if(cc=='-')f=-1;cc=getchar();}
while(cc>='0'&&cc<='9'){kk=(kk<<1)+(kk<<3)+cc-'0';cc=getchar();}
return kk*f;
}
LL n,k,a[211111],asd;
int main()
{
n=read();k=read();LL tot=0;
for(int i=1;i<=n;++i)
{
a[i]=read();tot+=a[i];
}
sort(a+1,a+1+n);
LL l=ceil((float)tot/n),r=a[n];asd=r;
while(l<=r)
{
LL mid=l+(r-l)/2;
tot=0;int i=lower_bound(a+1,a+1+n,mid)-a;
for(;i<=n;++i)if(a[i]-mid>0)tot+=a[i]-mid;
if(tot<=k)
{
asd=min(asd,mid);r=mid-1;
}
else l=mid+1;
}
cout<<asd;
}