AtCoder Beginner Contest 359 解题报告

AtCoder Beginner Contest 359

吐槽:A-F 还算正常,G 题你 tm 给我放了个出过的板子(ABC340G)是几个意思啊???

A

Simulate.

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define endl '\n'
#define PB emplace_back
#define PPB pop_back
#define MP make_pair
#define ALL(Name) Name.begin(),Name.end()
#define PII pair<int,int>
#define VI vector<int>
#define GI greater<int>
#define fi first
#define se second

int main()
{
	ios::sync_with_stdio(false),cin.tie(nullptr);
//	int _;cin>>_;while(_--)

	int n,ans=0;cin>>n;string s;
	while(n--)cin>>s,ans+=s[0]=='T';
	cout<<ans;

	return 0;
}

B

Simulate.

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define endl '\n'
#define PB emplace_back
#define PPB pop_back
#define MP make_pair
#define ALL(Name) Name.begin(),Name.end()
#define PII pair<int,int>
#define VI vector<int>
#define GI greater<int>
#define fi first
#define se second

int main()
{
	ios::sync_with_stdio(false),cin.tie(nullptr);
//	int _;cin>>_;while(_--)

	int n,ans=0;VI f[101];
	cin>>n;
	for(int i=1,x;i<=n<<1;i++)cin>>x,f[x].PB(i);
	for(int i=1;i<=n;i++)ans+=f[i][1]-f[i][0]==2;
	cout<<ans;

	return 0;
}

C

如果横着能免费移一下就先移,然后上一步靠近一步,上到等高就直接横着就行了。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define endl '\n'
#define PB emplace_back
#define PPB pop_back
#define MP make_pair
#define ALL(Name) Name.begin(),Name.end()
#define PII pair<int,int>
#define VI vector<int>
#define GI greater<int>
#define fi first
#define se second

int main()
{
	ios::sync_with_stdio(false),cin.tie(nullptr);
//	int _;cin>>_;while(_--)

	ll a,b,c,d;
	cin>>a>>b>>c>>d;
	if(a<c&&!((a+b)&1))a++;
	if(a<c&&((c+d)&1))c--;
	if(a>c&&((a+b)&1))a--;
	if(a>c&&!((c+d)&1))c++;
	cout<<abs((d-b))+max(0ll,(abs(a-c)-abs(d-b)+1)>>1);

	return 0;
}

D

直接状压即可。\(\Theta(n2^k)\),下列实现多一个 \(k\) 的复杂度,但是可以优化掉。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define endl '\n'
#define PB emplace_back
#define PPB pop_back
#define MP make_pair
#define ALL(Name) Name.begin(),Name.end()
#define PII pair<int,int>
#define VI vector<int>
#define GI greater<int>
#define fi first
#define se second

const int N=1005,MOD=998244353;
int n,k,dp[N][512];
string s;

int main()
{
	ios::sync_with_stdio(false),cin.tie(nullptr);
//	int _;cin>>_;while(_--)

	cin>>n>>k>>s;s="$"+s;
	dp[0][0]=1;
	for(int i=1;i<=n;i++)
		for(int j=0;j<1<<k-1;j++)
		{
			if(s[i]!='B')
			{//A
				bool ok=0;
				if(i<k)ok=1;
				int nxt=j<<1;
				for(int l=0;l<k>>1;l++)
					if(((nxt>>l)&1)!=((nxt>>k-l-1)&1))
					{ok=1;break;}
				if(ok)(dp[i][nxt&((1<<k-1)-1)]+=dp[i-1][j])%=MOD;
			}
			if(s[i]!='A')
			{//B
				bool ok=0;
				if(i<k)ok=1;
				int nxt=(j<<1)|1;
				for(int l=0;l<k>>1;l++)
					if(((nxt>>l)&1)!=((nxt>>k-l-1)&1))
					{ok=1;break;}
				if(ok)(dp[i][nxt&((1<<k-1)-1)]+=dp[i-1][j])%=MOD;
			}
		}
	int ans=0;
	for(int i=0;i<1<<k-1;i++)(ans+=dp[n][i])%=MOD;
	cout<<ans;

	return 0;
}

E

手模一下就可以发现:\(i\) 的答案就是所有的(\(i\) 结尾的)后缀极大值乘上距离上一个极大值的距离的和。单调栈维护即可。\(\Theta(n)\)

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define endl '\n'
#define PB emplace_back
#define PPB pop_back
#define MP make_pair
#define ALL(Name) Name.begin(),Name.end()
#define PII pair<int,int>
#define VI vector<int>
#define GI greater<int>
#define fi first
#define se second

const int N=200005;
int n;

int main()
{
	ios::sync_with_stdio(false),cin.tie(nullptr);
//	int _;cin>>_;while(_--)

	cin>>n;
	ll ans=1;
	vector<PII>f;
	f.PB(0,INT_MAX);
	for(int i=1,x;i<=n;i++)
	{
		cin>>x;
		int lst,lx;
		while(f.back().se<=x)
		{
			lst=f.back().fi,lx=f.back().se;
			f.PPB();
			ans-=1ll*(lst-f.back().fi)*lx;
		}
		ans+=1ll*x*(i-f.back().fi);
		f.PB(i,x);
		cout<<ans<<" ";
	}

	return 0;
}

F

能构成树的充要条件就是:

  • \(\forall1\le i\le n,d_i\ge1\),且
  • \(\displaystyle\sum_{i=1}^nd_i=2n-2\)

直接先把全部 \(d_i\) 赋上 \(1\) 的权值,后面用 pq 维护 \(n-2\) 次贪心即可。\(\Theta(n\log n)\)

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define endl '\n'
#define PB emplace_back
#define PPB pop_back
#define MP make_pair
#define ALL(Name) Name.begin(),Name.end()
#define PII pair<int,int>
#define VI vector<int>
#define GI greater<int>
#define fi first
#define se second

const int N=200005;
int n,a[N],d[N];
ll ans;
priority_queue<pair<ll,int>,vector<pair<ll,int> >,greater<pair<ll,int> > >q;

int main()
{
	ios::sync_with_stdio(false),cin.tie(nullptr);
//	int _;cin>>_;while(_--)

	cin>>n;
	for(int i=1;i<=n;i++)cin>>a[i],ans+=a[i],d[i]=1,q.emplace(3ll*a[i],i);
	for(int i=1;i<=n-2;i++)
	{
		int id=q.top().se;
		ans+=q.top().fi;
		q.pop();
		d[id]++;
		q.emplace(a[id]*(d[id]*2ll+1),id);
	}
	cout<<ans;

	return 0;
}

G

虚树板子。

直接对于某种颜色建虚树,然后就变成了无色的点对距离和问题,这是简单的。\(\Theta(n\log n)\)

虚树是拷的 ABC340G。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define endl '\n'
#define PB emplace_back
#define PPB pop_back
#define MP make_pair
#define ALL(Name) Name.begin(),Name.end()
#define PII pair<int,int>
#define VI vector<int>
#define GI greater<int>
#define fi first
#define se second

const int N=200005,L=18;
int n,c[N];
VI col[N],g[N];
int dfn[N],nfd[N],df,fa[N],dep[N],rmq[N][L];
void dfs(int x,int f)
{
	dfn[x]=++df,nfd[df]=x,fa[x]=f,dep[x]=dep[f]+1;
	for(int y:g[x])
		if(y!=f)dfs(y,x);
}
int RMQ(int l,int r)
{
	int g=31-__builtin_clz(r-l+1);
	return min(rmq[l][g],rmq[r-(1<<g)+1][g],[&](int x,int y){return dep[x]<dep[y];});
}
int lca(int x,int y)
{
	if(x==y)return x;
	return fa[RMQ(dfn[x]+1,dfn[y])];
}
ll solve(VI &p,int co)
{
	if(p.empty())return 0;
	vector<pair<int,bool>>v;
	vector<VI>vg;
	sort(ALL(p),[&](int x,int y){return dfn[x]<dfn[y];});
	v.PB(p[0],0);
	for(int i=1;i<p.size();i++)
	{
		v.PB(p[i],0);
		v.PB(lca(p[i-1],p[i]),0);
	}
	sort(ALL(v),[&](pair<int,bool> x,pair<int,bool> y){return dfn[x.fi]<dfn[y.fi];});
	v.erase(unique(ALL(v)),v.end());
	for(auto &i:v)if(c[i.fi]==co)i.se=1;
	map<int,int>id;
	for(int i=0;i<v.size();i++)id[v[i].fi]=i;
	vg.resize(v.size());
	for(int i=1;i<v.size();i++)
		vg[id[lca(v[i-1].fi,v[i].fi)]].PB(id[v[i].fi]);
	ll res=0;
	VI sz(v.size());
	auto dfs2=[&](auto dfs2,int x)->void
	{
		dbg(co,v[x].fi);
		sz[x]=v[x].se;
		for(int y:vg[x])
		{
			dfs2(dfs2,y),sz[x]+=sz[y];
			dbg(v[y].fi,sz[y],dep[v[y].fi],dep[v[x].fi]);
			res+=1ll*sz[y]*(p.size()-sz[y])*(dep[v[y].fi]-dep[v[x].fi]);
		}
	};
	dfs2(dfs2,0);
	dbg(co,res);
	return res;
}

int main()
{
	ios::sync_with_stdio(false),cin.tie(nullptr);
//	int _;cin>>_;while(_--)

	cin>>n;
	for(int i=1,u,v;i<n;i++)cin>>u>>v,g[u].PB(v),g[v].PB(u);
	for(int i=1;i<=n;i++)cin>>c[i],col[c[i]].PB(i);
	dfs(1,0);
	for(int i=n;i;i--)
	{
		rmq[i][0]=nfd[i];
		for(int j=1;i+(1<<j)-1<=n;j++)
			rmq[i][j]=min(rmq[i][j-1],rmq[i+(1<<j-1)][j-1],[&](int x,int y){return dep[x]<dep[y];});
	}
	ll ans=0;
	for(int i=1;i<=n;i++)ans+=solve(col[i],i);
	cout<<ans;

	return 0;
}
posted @ 2024-06-22 21:40  No_Play_Yes_Splay  阅读(343)  评论(0编辑  收藏  举报