2024/9/26/27/28

这几天专题和比赛太多了,所以写到一起了。

[ABC351G] Hash on Tree

首先暴力的 \(DP\) 很简单。

然后尝试每次操作在链上修改,看看能不能卡过去。结果写了我 30min 还是被数据卡了。

于是只能去写正解的 \(DDP\)

先是 131 行的树剖,又是 62 行的线段树维护矩乘。然后在纸上推了推矩乘,胡了个转移方程(我绝对不会说我推错了后去看了题解)。

然后调了 76min 调过了。

[ABC130D] Enough Array

因为下午还有模拟赛,所以果断放弃难题去水 ABC。

一个简单的二分前缀和查找区间个数。

小学不等式一推过掉(我爱水题)。

点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
inline int read()
{
	int w=1,s=0;char ch=getchar();
	while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();}
	while(isdigit(ch)){s=s*10+(ch-'0');ch=getchar();}
	return w*s;
}
const int mod=998244353;
const int maxn=2e5+10;
const int inf=-1e9-7;
int n,k;
int sum[maxn],a[maxn],ans;
signed main()
{
#ifdef Lydic
	freopen(".in","r",stdin);
	freopen(".out","w",stdout);
// #else
// 	freopen("defense.in","r",stdin);
// 	freopen("defense.out","w",stdout);
#endif
    cin>>n>>k;
	for(int i=1;i<=n;i++)a[i]=read(),sum[i]=sum[i-1]+a[i];
	for(int i=1;i<=n;i++)
	{
		int pos=lower_bound(sum+i,sum+n+1,sum[i-1]+k)-sum;
		ans+=(n-pos+1);
	}
	cout<<ans;
    return 0;
}

[ABC127D] Integer Cards

首先贪心选择最小值更新。

发现直接更新的话复杂度巨大。

于是加上小技巧,把操作离线后排个序再更新保证每个元素的更新次数。

然后就过了。

点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
inline int read()
{
	int w=1,s=0;char ch=getchar();
	while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();}
	while(isdigit(ch)){s=s*10+(ch-'0');ch=getchar();}
	return w*s;
}
const int mod=998244353;
const int maxn=2e5+10;
const int inf=-1e9-7;
int n,m;
struct no
{
	int b,c;
	inline friend bool operator < (no x,no y)
	{
		return x.c>y.c;
	}
}a[maxn];
priority_queue<int,vector<int>,greater<int> > q;
signed main()
{
#ifdef Lydic
	freopen(".in","r",stdin);
	freopen(".out","w",stdout);
// #else
// 	freopen("defense.in","r",stdin);
// 	freopen("defense.out","w",stdout);
#endif
    cin>>n>>m;
	for(int i=1;i<=n;i++)q.push(read());
	for(int i=1;i<=m;i++)a[i]={read(),read()};
	sort(a+1,a+m+1);
	for(int i=1;i<=m;i++)
	{
		while(a[i].b)
		{
			int u=q.top();
			if(u>=a[i].c)break;
			q.pop();
			u=a[i].c;
			q.push(u);
			a[i].b--;
		}
	}
	int ans=0;
	while(!q.empty())ans+=q.top(),q.pop();
	cout<<ans;
    return 0;
}

[ABC122C] GeT AC

这不一眼前缀和?

写完以后发现样例假了。

但是简单思考发现只有当 AC 两个字符分别在 \(l-1\)\(l\) 的位置上的时候才会出错。

于是加上特判,轻松过掉。

点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
inline int read()
{
	int w=1,s=0;char ch=getchar();
	while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();}
	while(isdigit(ch)){s=s*10+(ch-'0');ch=getchar();}
	return w*s;
}
const int mod=998244353;
const int maxn=2e5+10;
const int inf=-1e9-7;
int n,Q;
char s[maxn];
int sum[maxn];
signed main()
{
#ifdef Lydic
	freopen(".in","r",stdin);
	freopen(".out","w",stdout);
// #else
// 	freopen("defense.in","r",stdin);
// 	freopen("defense.out","w",stdout);
#endif
    cin>>n>>Q;
	scanf("%s",s+1);
	for(int i=1;i<=n;i++)
	{
		if(s[i]=='C'&&s[i-1]=='A')sum[i]=sum[i-2]+1;
		else sum[i]=sum[i-1];
	}
	while(Q--)
	{
		int l=read(),r=read();
		int ans=sum[r]-sum[l-1];
		if(s[l-1]=='A'&&s[l]=='C')ans--;
		printf("%lld\n",ans);
	}
    return 0;
}

P6021 洪水

看着排行榜打算回来继续 DDP。

和第一题比较类似的常规 DDP。

写了 50min,开始调。

调到吃完饭,调到睡午觉。

然后发现:

image

晕倒了。

[ABC136E] Max GCD

考炸了,回来水题和题解。

题目翻译没看懂,上 AT 发现 deepl 都比翻译好。

想了一会发现一个必要条件,于是可以通过反推验证的方法找到所有可能解。

对于验证的话发现可以按照模数排序以后双指针贪心搞。

写完以后发现错了,接下来是最唐的时刻:

唐1

image
验证模数取了个常量。

唐2

image
数组大小和模数大小搞反了。

唐3

image
优先级搞错了。

终于过了:

点击查看代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
inline int read()
{
	int w=1,s=0;char ch=getchar();
	while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();}
	while(isdigit(ch)){s=s*10+(ch-'0');ch=getchar();}
	return w*s;
}
const int mod=1e9+7;
const int maxn=3e3+10;
const int inf=1e9+7;
int n,k,a[maxn],sum,b[maxn];
bool ch(int x)
{
    for(int i=1;i<=n;i++)b[i]=a[i]%mod;
    sort(b+1,b+n+1);
    int l=1,r=n,res=0;
    while(l<=r)
    {
        for(;b[l]&&l<=r;l++);
        for(;b[r]&&l<=r;r--);
        int mi=min(b[l]%x,x-b[r]%x);
        b[l]-=mi;b[r]+=mi;
        res+=mi;
    }
    return res<=k;
}
signed main()
{
#ifdef Lydic
	freopen(".in","r",stdin);
	freopen(".out","w",stdout);
// #else
//  	freopen("Oros.in","r",stdin);
//  	freopen("Oros.out","w",stdout);
#endif
	cin>>n>>k;
    for(int i=1;i<=n;i++)a[i]=read(),sum+=a[i];
    int ans=1;
    for(int i=1;i<=sqrt(sum*1.0);i++)
    {
        if(sum%i)continue;
        int j=sum/i;
        ans=max({ans,(ch(i)?i:-inf),(ch(j)?j:-inf)});
    }
    cout<<ans;
	return 0;
}

[ARC145C] Split and Maximize

小清新结论题。

首先瞪眼可知使结果最大的构造方案。

然后考虑使结果不变的情况下如何产生不同的方案数。

加法和乘法原理分别讨论一下,然后就推到了卡特兰数,结果甚至不需要求组合数,边乘边取余即可。

点击查看代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
inline int read()
{
	int w=1,s=0;char ch=getchar();
	while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();}
	while(isdigit(ch)){s=s*10+(ch-'0');ch=getchar();}
	return w*s;
}
const int mod=998244353;
const int maxn=4e5+10;
const int inf=1e9+7;
int n;
int qw(int x,int y)
{
	int ans=1;
    while(y)
    {
        if(y&1)ans=ans*x%mod;
        x=x*x%mod;
        y>>=1;
    }
    return ans;
}
signed main()
{
#ifdef Lydic
	freopen(".in","r",stdin);
	freopen(".out","w",stdout);
//  #else
//   	freopen("Boreas.in","r",stdin);
//   	freopen("Boreas.out","w",stdout);
#endif
	cin>>n;
	int ans=qw(2,n);	
	for(int i=n+2;i<=2*n;i++)ans=ans*i%mod;
	cout<<ans;
	return 0;

}

[ABC026D] 高橋君ボール1号

一眼觉得函数不单增好像只能模拟退火(我也不会),两眼发现根据题目要求我们只需要找到一组可行解,所以二分即使不能找到所有解,最终也一定能停留到某一个正确的解,因此可行。

写完以后发现样例误差很大,怎么调都调不过来,一怒之下直接交,然后就过了?然后发现题目是SPJ

点击查看代码
#include <bits/stdc++.h>
#define int long long
#define pi 3.141592653589793
using namespace std;
inline int read()
{
	int w=1,s=0;char ch=getchar();
	while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();}
	while(isdigit(ch)){s=s*10+(ch-'0');ch=getchar();}
	return w*s;
}
const int mod=998244353;
const int maxn=4e5+10;
const int inf=1e10+7;
double a,b,c;
bool ch(double x)
{
	return a*x+b*sin(c*x*pi)>100;
}
signed main()
{
#ifdef Lydic
	freopen(".in","r",stdin);
	freopen(".out","w",stdout);
//  #else
//   	freopen("Boreas.in","r",stdin);
//   	freopen("Boreas.out","w",stdout);
#endif
	cin>>a>>b>>c;
	double l=1,r=1e9+7;
	for(int i=1;i<=6e6;i++)
	{
		double mid=(l+r)/2.00;
        if(ch(mid))r=mid;
        else l=mid;
	}
	printf("%.10lf",l);
	return 0;

}

[ABC204D]Cooking

比较熟悉的套路。

把题意经过两次转化以后可以得到一个 01 背包,然后我们就直接做。

点击查看代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
inline int read()
{
	int w=1,s=0;char ch=getchar();
	while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();}
	while(isdigit(ch)){s=s*10+(ch-'0');ch=getchar();}
	return w*s;
}
const int mod=998244353;
const int maxn=4e5+10;
const int inf=1e9+7;
int n,a[maxn],sum;
int dp[120][200000];
signed main()
{
#ifdef Lydic
	freopen(".in","r",stdin);
	freopen(".out","w",stdout);
//  #else
//   	freopen("Boreas.in","r",stdin);
//   	freopen("Boreas.out","w",stdout);
#endif
	cin>>n;
	for(int i=1;i<=n;i++)a[i]=read(),sum+=a[i];
	for(int i=1;i<=n;i++)
	{
		for(int j=sum/2;j>=a[i];j--)
		{
			dp[i][j]=max(dp[i-1][j],dp[i-1][j-a[i]]+a[i]);
		}
	}
	cout<<sum-dp[n][sum/2];
	return 0;

}

[ABC322C] Festival

本来是来看 D 的,但是不会,所以去看 C 了。发现可以水。

一个不加任何掩饰的二分。

点击查看代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
inline int read()
{
	int w=1,s=0;char ch=getchar();
	while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();}
	while(isdigit(ch)){s=s*10+(ch-'0');ch=getchar();}
	return w*s;
}
const int mod=998244353;
const int maxn=4e5+10;
const int inf=1e9+7;
int n,m,a[maxn];

signed main()
{
#ifdef Lydic
	freopen(".in","r",stdin);
	freopen(".out","w",stdout);
//  #else
//   	freopen("Boreas.in","r",stdin);
//   	freopen("Boreas.out","w",stdout);
#endif
	cin>>n>>m;
	for(int i=1;i<=m;i++)a[i]=read();
	for(int i=1;i<=n;i++)
	{
		int pos=a[lower_bound(a+1,a+m+1,i)-a];
		cout<<pos-i<<endl;
	}
	return 0;

}

[EC Final 2021] DFS Order

看见 Final 还以为是什么难题,然后简单想了一下发现只需要求解每个节点的深度和子树大小即可。

一开始因为 memset T 了一发。

点击查看代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
inline int read()
{
	int w=1,s=0;char ch=getchar();
	while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();}
	while(isdigit(ch)){s=s*10+(ch-'0');ch=getchar();}
	return w*s;
}
const int mod=1e9+7;
const int maxn=2e5+10;
const int inf=1e9+7;
int n,dep[maxn],siz[maxn];
vector<int> G[maxn];
void dfs(int x,int fa)
{
	dep[x]=dep[fa]+1;
    siz[x]=1;
    for(auto y:G[x])
    {
        if(y==fa)continue;
		dfs(y,x);
        siz[x]+=siz[y];
    }
}
void Main()
{
	n=read();
	for(int i=1;i<=n;i++)G[i].clear();
	for(int i=1;i<=n;i++)dep[i]=siz[i]=0;
	for(int i=1;i<n;i++)
	{
		int x=read(),y=read();
		G[x].push_back(y);
		G[y].push_back(x);
	}
	dfs(1,0);
	for(int i=1;i<=n;i++)
	{
		printf("%lld %lld\n",dep[i],n-siz[i]+1);
	}
}
signed main()
{
#ifdef Lydic
	freopen(".in","r",stdin);
	freopen(".out","w",stdout);
//  #else
//   	freopen("Zephyros.in","r",stdin);
//   	freopen("Zephyros.out","w",stdout);
#endif  
	int T=read();
	while(T--)Main();
    return 0;

}

[ARC115A] Two Choices

一开始盲目 set 发现样例过不去,以为是代码问题,但是在纸上推了推发现没问题。再看一眼题发现题读错了(我是废物

根据题目条件可以很好地根据 \(0\) 的奇偶性找到一个规律,然后用个桶统计一下就行了。

点击查看代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
inline int read()
{
	int w=1,s=0;char ch=getchar();
	while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();}
	while(isdigit(ch)){s=s*10+(ch-'0');ch=getchar();}
	return w*s;
}
const int mod=1e9+7;
const int maxn=2e5+10;
const int inf=1e9+7;
int n,m;
int a[maxn][25];
int b[maxn];
multiset<int> se; 
int f[maxn*25];
signed main()
{
#ifdef Lydic
	freopen(".in","r",stdin);
	freopen(".out","w",stdout);
// #else
//    	freopen("brike.in","r",stdin);
//    	freopen("brike.out","w",stdout);
#endif  
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	{
		int sum=0;
		for(int j=1;j<=m;j++)
		{
			char c;cin>>c;
			b[i]+=(c=='0');	
		}
		f[b[i]%2]++;
	}
	cout<<f[0]*f[1]<<endl;
    return 0;

}
posted @ 2024-09-26 11:23  Redamancy_Lydic  阅读(17)  评论(0编辑  收藏  举报