Codeforces Round #790 (Div. 4) 【题解】

好菜好菜呀。差不多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;
}

猜你喜欢

转载自blog.csdn.net/qq_46527915/article/details/124811258