好菜好菜呀。差不多1.5h才AK。
看了一下几个朋友都是30-50分钟就AK了。感觉自己真的是太菜了。
目录
A. Lucky?【签到】
#include<bits/stdc++.h>
using namespace std;
int main(void)
{
int t; cin>>t;
while(t--)
{
string s; cin>>s;
int cnt1=0,cnt2=0;
for(int i=0;i<=2;i++) cnt1+=s[i]-'0';
for(int i=3;i<6;i++) cnt2+=s[i]-'0';
if(cnt1==cnt2) puts("YES");
else puts("NO");
}
return 0;
}
B. Equal Candies【签到】
#include<bits/stdc++.h>
using namespace std;
int a[105];
int main(void)
{
int t; cin>>t;
while(t--)
{
int n; cin>>n;
int minv=1e9,sum=0;
for(int i=0;i<n;i++) cin>>a[i],minv=min(minv,a[i]);
for(int i=0;i<n;i++) sum+=a[i]-minv;
cout<<sum<<'\n';
}
return 0;
}
C. Most Similar Words【暴力枚举】
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int n,m,t;
string s[N];
int solve(string a,string b)
{
int cnt=0;
for(int i=0;i<a.size();i++)
{
if(a[i]==b[i]) continue;
char c1=a[i],c2=b[i];
if(c1>c2) swap(c1,c2);
int len=c2-c1;
cnt+=len;
}
return cnt;
}
int main(void)
{
cin>>t;
while(t--)
{
cin>>n>>m;
for(int i=0;i<n;i++) cin>>s[i];
int ans=1e9;
for(int i=0;i<n;i++)
for(int j=i+1;j<n;j++)
ans=min(solve(s[i],s[j]),ans);
cout<<ans<<'\n';
}
return 0;
}
D. X-Sum【枚举+模拟】
#include<bits/stdc++.h>
using namespace std;
typedef long long int LL;
const int N=210;
int n,m,t;
LL a[N][N];
LL solve(int x,int y)
{
LL sum=0;
for(int i=x,j=y;i>=1&&j>=1;i--,j--) sum+=a[i][j];
for(int i=x+1,j=y+1;i<=n&&j<=m;i++,j++) sum+=a[i][j];
for(int i=x-1,j=y+1;i>=1&&j<=m;i--,j++) sum+=a[i][j];
for(int i=x+1,j=y-1;i<=n&&j>=1;i++,j--) sum+=a[i][j];
return sum;
}
int main(void)
{
cin>>t;
while(t--)
{
cin>>n>>m;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++) cin>>a[i][j];
LL sum=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++) sum=max(sum,solve(i,j));
cout<<sum<<'\n';
}
return 0;
}
E. Eating Queries【前缀和+二分】
#include<bits/stdc++.h>
using namespace std;
typedef long long int LL;
const int N=1e5*5+10;
int n,m,t;
LL a[N],s[N];
bool cmp(LL a,LL b){
return a>b;}
int main(void)
{
cin>>t;
while(t--)
{
cin>>n>>m;
for(int i=0;i<n;i++) cin>>a[i];
sort(a,a+n,cmp);
s[0]=a[0];
for(int i=1;i<n;i++) s[i]=s[i-1]+a[i];
while(m--)
{
LL x; cin>>x;
int len=lower_bound(s,s+n,x)-s;
if(s[len]>=x&&len<n) cout<<len+1<<'\n';
else cout<<-1<<'\n';
}
}
return 0;
}
F. Longest Strike【双指针】
中间因为双指针忘了移动,T麻了。后来才找到bug。
#include<bits/stdc++.h>
using namespace std;
typedef long long int LL;
const int N=1e5*5+10;
int n,t,k;
int a[N];
int main(void)
{
cin>>t;
while(t--)
{
cin>>n>>k;
map<int,int>mp;
for(int i=1;i<=n;i++) cin>>a[i],mp[a[i]]++;
vector< pair<LL,LL> >ve;
int flag=0;
for(auto i=mp.begin();i!=mp.end();i++)
ve.push_back({
i->first,i->second});
LL l=0,r=0,ans=0;
sort(ve.begin(),ve.end());
for(int i=0;i<ve.size();i++)
{
if(ve[i].second>=k)
{
int j=i;
while(j+1<ve.size()&&(ve[j+1].first-ve[j].first==1)&&ve[j+1].second>=k) j++;
if((ve[j].first-ve[i].first+1)>ans)
ans=ve[j].first-ve[i].first+1,l=ve[i].first,r=ve[j].first;
i=j;
}
}
if(!ans) cout<<-1<<'\n';
else cout<<l<<" "<<r<<'\n';
}
return 0;
}
G. White-Black Balanced Subtrees【dfs / 树形DP】
就是求子树的点的黑白个树是否相同。写了一下但是短路了。
于是直接用dfs序+树状数组暴力来搞。
#include<bits/stdc++.h>
using namespace std;
const int N=1e5*4+10;
int h[N],e[N],ne[N],w[N],idx;
int in[N],out[N],timestep;//进入的时间 退出的时间 时间戳
int n,m,t,st[N],tr[N];
void add(int a,int b)
{
e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
void dfs(int u,int fa)
{
in[u]=++timestep;//进入的时间戳
for(int i=h[u];i!=-1;i=ne[i])
{
int j=e[i];
if(j==fa) continue;
dfs(j,u);
}
out[u]=timestep;//遍历完所有的子树退出的时间戳
}
int lowbit(int x){
return x&(-x);}
void update(int x,int c)
{
for(int i=x;i<=n;i+=lowbit(i)) tr[i]+=c;
}
int query(int x)
{
int sum=0;
for(int i=x;i;i-=lowbit(i)) sum+=tr[i];
return sum;
}
void init(int n)
{
for(int i=0;i<=n;i++) tr[i]=0,h[i]=-1;
idx=0;
timestep=0;
}
int main(void)
{
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
cin>>t;
while(t--)
{
cin>>n;
init(n);
for(int i=2;i<=n;i++)
{
int x; cin>>x;
add(x,i),add(i,x);
}
string s; cin>>s;
for(int i=0;i<s.size();i++)
if(s[i]=='W') w[i+1]=0;//将白的权值弄成1
else w[i+1]=1;//黑的弄成0
dfs(1,-1);
for(int i=1;i<=n;i++) update(in[i],w[i]);//in[i] i号结点在dfs序列中的位置
int ans=0;
for(int i=1;i<=n;i++)
{
int sum=query(out[i])-query(in[i]-1);//白的个数
int len=out[i]-in[i]+1;//总的个数
if( (len-sum==sum )&&sum) ans++;
}
cout<<ans<<'\n';
}
return 0;
}
树形DP做法。
#include<bits/stdc++.h>
using namespace std;
const int N=4010;
vector<int>ve[N];
int f[N][2];//0 w 1 B
string s;
void dfs(int u,int fa)
{
if(s[u]=='W') f[u][0]++;
else f[u][1]++;
for(int i=0;i<ve[u].size();i++)
{
int j=ve[u][i];
if(j==fa) continue;
dfs(j,u);
f[u][0]+=f[j][0],f[u][1]+=f[j][1];
}
}
int main(void)
{
int t; cin>>t;
while(t--)
{
int n; cin>>n;
for(int i=1;i<=n;i++) ve[i].clear(),f[i][0]=0,f[i][1]=0;
for(int i=2;i<=n;i++)
{
int x; cin>>x;
ve[x].push_back(i),ve[i].push_back(x);
}
cin>>s;
s="0"+s;
dfs(1,-1);
int cnt=0;
for(int i=1;i<=n;i++) if(f[i][0]==f[i][1]) cnt++;
cout<<cnt<<'\n';
}
return 0;
}
H1. Maximum Crossings (Easy Version)【树状数组】
发现规律,就是求逆序对的数量即可。树状数组来搞。
#include<bits/stdc++.h>
using namespace std;
typedef long long int LL;
const int N=1e5*2+10;
int t,n,a[N],tr[N];
int lowbit(int x){
return x&(-x);}
void update(int x,LL v)
{
for(int i=x;i<N;i+=lowbit(i)) tr[i]+=v;
}
LL query(int x)
{
LL sum=0;
for(int i=x;i;i-=lowbit(i)) sum+=tr[i];
return sum;
}
int main(void)
{
cin>>t;
while(t--)
{
cin>>n;
for(int i=0;i<=n+10;i++) tr[i]=0;
for(int i=1;i<=n;i++) cin>>a[i];
LL ans=0;
for(int i=1;i<=n;i++)
{
ans+=query(n+1)-query(a[i]-1);
update(a[i],1);
}
cout<<ans<<'\n';
}
return 0;
}
H2. Maximum Crossings (Hard Version)【树状数组】
#include<bits/stdc++.h>
using namespace std;
typedef long long int LL;
const int N=1e5*2+10;
int t,n,a[N],tr[N];
int lowbit(int x){
return x&(-x);}
void update(int x,LL v)
{
for(int i=x;i<N;i+=lowbit(i)) tr[i]+=v;
}
LL query(int x)
{
LL sum=0;
for(int i=x;i;i-=lowbit(i)) sum+=tr[i];
return sum;
}
int main(void)
{
cin>>t;
while(t--)
{
cin>>n;
for(int i=0;i<=n+10;i++) tr[i]=0;
for(int i=1;i<=n;i++) cin>>a[i];
LL ans=0;
for(int i=1;i<=n;i++)
{
ans+=query(n+1)-query(a[i]-1);
update(a[i],1);
}
cout<<ans<<'\n';
}
return 0;
}