返回顶部

CSP25

挂分大赛

警钟长鸣
总计,挂了至少155
T1输出忘考虑负数 挂80
T3全\(RE\)挂75

T1

题目

image

线段树暴力能过
注意考虑负数啊,挂了\(80\)

点击查看代码
#include <bits/stdc++.h>
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define ll long long
// #define endl '\n'
#define pii pair<int,int>
#define lid (rt<<1)
#define rid (rt<<1|1)
#define ull unsigned long long
#define pb push_back
#define ts cout<<"----------------"<<endl;
#define bs bitset<65>
using namespace std;
const int N = 1e5+5,mod=998244353;
int n,m;ll a[N];
int tot;
int op[N],tms;
struct ST
{
	int st,id;
};
struct Q
{
	int l,r,x,op;
}q[N];
struct T
{
	ll l,r;ll w,lz;
}st[N<<2];
inline void pushup(int rt)
{
	st[rt].w=(st[lid].w+st[rid].w)%mod;
}
inline void pd(int rt)
{
	if(st[rt].lz)
	{
		ll lz=st[rt].lz%mod;st[rt].lz=0;
		st[lid].lz=(st[lid].lz+lz)%mod;
		st[rid].lz=(st[rid].lz+lz)%mod;
		st[lid].w=(st[lid].w+lz*(st[lid].r-st[lid].l+1)%mod)%mod;
		st[rid].w=(st[rid].w+lz*(st[rid].r-st[rid].l+1)%mod)%mod;
	}
}
inline void build(int rt,int l,int r)
{
	st[rt].l=l;st[rt].r=r;
	if(l==r)
	{
		st[rt].w=a[l];return;
	}
	int mid=(l+r)>>1;
	build(lid,l,mid);build(rid,mid+1,r);
	pushup(rt);
}
void update(int rt,int l,int r,ll v)
{
	if(l<=st[rt].l&&st[rt].r<=r)
	{
		st[rt].w=(st[rt].w+v*(st[rt].r-st[rt].l+1)%mod)%mod;
		st[rt].lz=(st[rt].lz+v)%mod;return;
	}
	int mid=(st[rt].l+st[rt].r)>>1;
	pd(rt);
	if(l<=mid)update(lid,l,r,v);
	if(r>mid)update(rid,l,r,v);
	pushup(rt);
}
ll query(int rt,int l,int r)
{
	if(l<=st[rt].l&&st[rt].r<=r)
	{
		return st[rt].w;
	}
	int mid=(st[rt].l+st[rt].r)>>1;
	pd(rt);
	ll ans=0;
	if(l<=mid)ans=(ans+query(lid,l,r))%mod;
	if(r>mid)ans=(ans+query(rid,l,r))%mod;
	// pushup(rt);
	return ans;
}
stack <int> Q;
int main()
{
	speed();
	// freopen("in.in","r",stdin);
	// freopen("out.out","w",stdout);
	cin>>n>>m;
	for(int i=1;i<=n;i++)cin>>a[i];
	build(1,1,n);
	int now=0;
	for(int i=1;i<=m;i++)
	{
		cin>>q[i].op;
		if(q[i].op==1)
		{
			cin>>q[i].l>>q[i].r>>q[i].x;
			update(1,q[i].l,q[i].r,q[i].x);
			now++;
			Q.push(i);
		}else if(q[i].op==2)
		{
			cin>>q[i].l>>q[i].r;
			cout<<(query(1,q[i].l,q[i].r)+mod)%mod<<endl;
		}else 
		{
			cin>>q[i].x;
			now-=q[i].x;
			while(Q.size()!=now&&Q.size())
			{
				int id=Q.top();Q.pop();
				 // cout<<id<<endl;
				update(1,q[id].l,q[id].r,-q[id].x);
			}
		}
	}
	return 0;
}

T2

题目

image

我们可以先去掉\(Qie\)的边,然后只在\(Lun\)边上跑一边\(Tarjan\)找到所有的环,然后不是环的去掉就行了,剩下只需要构造一颗生成树,用并查集维护连通性,注意割边一定要删掉

点击查看代码
#include <bits/stdc++.h>
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define ll long long
// #define endl '\n'
#define pii pair<int,int>
#define ull unsigned long long
#define pb push_back
#define ts cout<<"----------------"<<endl;
#define bs bitset<65>
using namespace std;
const int N = 2e5+5;
int n,m;
struct node
{
	int v,w,id;
};
vector <node> edge[N];
struct node2
{
	int u,v,w,id;
};
vector <node2> e;
vector <int> ans;
int dfn[N],dfs_clock,low[N],belong[N],cnt,s[N],top;
bool del[N];stack <int> stk;
inline void Tarjan(int  u,int id)
{
	// cout<<u<<endl;
	dfn[u]=low[u]=++dfs_clock;
	stk.push(u);
	for(auto [to,w,i]:edge[u])
	{
		if(i==id)continue;
		if(!dfn[to])
		{
			Tarjan(to,i);
			low[u]=min(low[u],low[to]);
		}else
		{
			low[u]=min(low[u],dfn[to]);
		}
	}
	if(low[u]==dfn[u])
	{
		del[id]=1;//删割边
		int x=0;
		++cnt;
		do
		{
			x=stk.top();stk.pop();
			belong[x]=cnt;
		}while(x!=u);
	}
}
int fa[N];
int find(int u)
{
	if(u!=fa[u])fa[u]=find(fa[u]);
	return fa[u];
}
bool un(int u,int v)
{
	u=find(u),v=find(v);
	if(u!=v)
	{
		fa[u]=v;
		return 1;
	}
	return 0;
}
int main()
{
	speed();
	// freopen("puzzle13.in","r",stdin);
	// freopen("in.in","r",stdin);
	// freopen("out.out","w",stdout);
	cin>>n>>m;
	int u,v;
	char op[10];e.pb({0,0});
	for(int i=1;i<=m;i++)
	{
		cin>>u>>v>>op;
		if(op[0]=='L')
		{
			e.pb({u,v,1,i});
			edge[u].pb({v,1,i});edge[v].pb({u,1,i});
		}else
		{
			e.pb({u,v,2,i});
		}
	}
	for(int i=1;i<=n;i++)fa[i]=i;
	for(int i=1;i<=n;i++)
	{
		if(!dfn[i])Tarjan(i,0);
	}
	for(int i=1;i<=m;i++)
	{
		if(e[i].w==1&&!del[i])
		{
			int u=e[i].u,v=e[i].v;
			if(belong[u]==belong[v])
			{
				un(u,v);
				ans.pb(i);
			}
		}
	}
	// if(!ans.size())
	// {
	// 	cout<<"NO"<<endl;return 0;
	// }

	for(int i=1;i<=m;i++)
	{
		if(e[i].w==2)
		{
			int u=e[i].u,v=e[i].v;
			if(un(u,v))ans.pb(i);
		}
	}
	int fs=find(1);
	for(int i=2;i<=n;i++)
	{
		if(find(i)!=fs)
		{
			cout<<"NO"<<endl;return 0;	
		}
	}
	cout<<"YES"<<endl;
	// if(ans.size()!=n-1)
	// {
	// 	cout<<"NO"<<endl;return 0;
	// }
	// for(int i=1;i<=n;i++)
	cout<<ans.size()<<endl;
	for(auto v:ans)
	{
		cout<<e[v].u<<" "<<e[v].v<<endl;
	}
	return 0;
}
/*
./spj in.in out.out out.out
*/

用树状数组会飞快

点击查看代码
#include <bits/stdc++.h>
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define ll long long
// #define endl '\n'
#define pii pair<int,int>
#define lid (rt<<1)
#define rid (rt<<1|1)
#define ull unsigned long long
#define pb push_back
#define ts cout<<"----------------"<<endl;
#define bs bitset<65>
using namespace std;
const ll N = 5e5+5,mod=998244353;
int n,m;ll a[N];
int tot;
int op[N],tms;
inline int read()
{
	int x=0,f=1;char ch=getchar_unlocked();
	for(;ch<'0'||ch>'9';ch=getchar_unlocked())if(ch=='-')f=-1;
	for(;ch>='0'&&ch<='9';ch=getchar_unlocked())x=(x<<3)+(x<<1)+(ch^48);
	return x*f;	
}
inline void write(int x)
{
	return x<0?(putchar_unlocked('-'),write(-x),void(0)):(x==0?void(0):(write(x/10),putchar_unlocked((x%10)|48),void(0)));
}
struct ST
{
	int st,id;
};
struct Q
{
	int l,r,x,op;
}q[N];
ll c[N],c1[N];
int lowbit(int x)
{
	return x&-x;
}
void update(int x,ll v)
{
	ll v1=x*v;
	while(x<=n)
	{
		(c[x]+=v);
		(c1[x]+=v1);
		x+=lowbit(x);
	}
}
ll query(int x)
{
	ll tmp=x,ans=0,res1=0;
	while(x)
	{
		(ans+=c[x]);
		(res1+=c1[x]);
		x-=lowbit(x);
	}
	return (ans*(tmp+1)-res1);
}
stack <int> Q;
int main()
{
	// speed();
	freopen("in.in","r",stdin);
	freopen("out.out","w",stdout);
	n=read();m=read();
	for(int i=1;i<=n;i++)
	{
		a[i]=read();
		update(i,a[i]-a[i-1]);
	}
	int now=0;
	for(int i=1;i<=m;i++)
	{
		q[i].op=read();
		if(q[i].op==1)
		{
			q[i].l=read();q[i].r=read();q[i].x=read();
			update(q[i].l,q[i].x);
			update(q[i].r+1,-q[i].x);
			now++;
			Q.push(i);
		}else if(q[i].op==2)
		{
			q[i].l=read();q[i].r=read();
			write(query(q[i].r)-query(q[i].l-1));
			putchar_unlocked('\n');
			// cout<<((query(q[i].r)-query(q[i].l-1))%mod+mod)%mod<<endl;
		}else 
		{
			q[i].x=read();
			now-=q[i].x;
			while(Q.size()!=now&&Q.size())
			{
				int id=Q.top();Q.pop();
				 // cout<<id<<endl;
				update(q[id].l,-q[id].x);
				update(q[id].r+1,q[id].x);
			}
		}
	}
	return 0;
}

T3

题目

image

考虑\(dp_{i,j}\),表示构造长为\(i\)的序列,最后一个数为\(j\),\(O(nm^2)\)转移
用前缀和优化一下,优化到\(O(nm)\),数组别开太大,挂了\(75\)

如果要打表,可以\(vscode\)\(sublime\)并用,尽早开始啊

点击查看代码
#include <bits/stdc++.h>
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define ll long long
// #define endl '\n'
#define pii pair<int,int>
#define ull unsigned long long
#define pb push_back
#define ts cout<<"----------------"<<endl;
#define bs bitset<65>
using namespace std;
const int mod=998244353,N=1e6+5;
int n,m,mo[N];int dp[2][N];ll sum[2][N][3];
int main()
{
	speed();
	// freopen("in.in","r",stdin);
	// freopen("out1.out","w",stdout);
	cin>>n>>m;
	if(m==n-1)
	{
		cout<<1<<endl;return 0;
	}
	if(n>m)
	{
		cout<<0<<endl;
		return 0;
	}
	for(int i=0;i<=m;i++)dp[1][i]=1,sum[1][i][i%3]=(sum[1][i][i%3]+1)%mod;
	for(int j=0;j<=m;j++)
	{
		sum[1][j][0]=(sum[1][j-1][0]+sum[1][j][0])%mod;
		sum[1][j][1]=(sum[1][j-1][1]+sum[1][j][1])%mod;
		sum[1][j][2]=(sum[1][j-1][2]+sum[1][j][2])%mod;
		mo[j]=j%3;
	}
	// dp[0][0]=1;
	for(int i=2;i<=n;i++)
	{
		// for(int j=0;j<=m;j++)
		for(int j=0;j<=m;j++)
		{
			dp[i&1][j]=0,sum[i&1][j][0]=sum[i&1][j][1]=sum[i&1][j][2]=0;
			ll tmp=0;
			if(j>0)tmp=sum[(i-1)&1][j-1][0]*(mo[j]!=0)+sum[(i-1)&1][j-1][1]*(mo[j]!=1)+sum[(i-1)&1][j-1][2]*(mo[j]!=2);
			// cout<<tmp<<endl;
			tmp=(tmp%mod+mod)%mod;
			dp[i&1][j]=(dp[i&1][j]+tmp)%mod;
			sum[i&1][j][mo[j]]=(sum[i&1][j][mo[j]]+dp[i&1][j])%mod;
			// cout<<i<<" "<<j<<" "<<dp[i&1][j]<<endl;
		}
		for(int j=1;j<=m;j++)
		{
			sum[i&1][j][0]=(sum[i&1][j-1][0]+sum[i&1][j][0])%mod;
			sum[i&1][j][1]=(sum[i&1][j-1][1]+sum[i&1][j][1])%mod;
			sum[i&1][j][2]=(sum[i&1][j-1][2]+sum[i&1][j][2])%mod;
		}
	}
	ll ans=0;
	for(int i=n-1;i<=m;i++)ans=(ans+dp[n&1][i])%mod;
	cout<<ans<<endl;
	return 0;
}
/*
0 0 0
0 1 1
0 2 2
0 3 2
0 4 3
1 0 0
1 1 0
1 2 1
1 3 3
1 4 4
8



*/

其实,还可以优化,就是比较\(n,m\)大小关系,然后卡紧左右边界即可

点击查看代码
#include <bits/stdc++.h>
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define ll long long
// #define endl '\n'
#define pii pair<int,int>
#define ull unsigned long long
#define pb push_back
#define ts cout<<"----------------"<<endl;
#define bs bitset<65>
using namespace std;
const int mod=998244353,N=1e7+5;
int n,m,mo[N],l[N],r[N];int dp[2][N];int sum[2][N][3];
int main()
{
	speed();
	// freopen("in.in","r",stdin);
	// freopen("out1.out","w",stdout);
	cin>>n>>m;
	for(int i=1;i<=n;i++)
		l[i]=i-1,r[i]=m-(n-i);
	if(m==n-1)
	{
		cout<<1<<endl;return 0;
	}
	if(n>m)
	{
		cout<<0<<endl;
		return 0;
	}
	for(int i=0;i<=m;i++)dp[1][i]=1,sum[1][i][i%3]=(sum[1][i][i%3]+1)%mod;
	for(int j=0;j<=m;j++)
	{
		sum[1][j][0]=(sum[1][j-1][0]+sum[1][j][0])%mod;
		sum[1][j][1]=(sum[1][j-1][1]+sum[1][j][1])%mod;
		sum[1][j][2]=(sum[1][j-1][2]+sum[1][j][2])%mod;
		mo[j]=j%3;
	}
	// dp[0][0]=1;
	for(int i=2;i<=n;i++)
	{
		for(int j=l[i]-1;j<=r[i];j++)dp[i&1][j]=0,sum[i&1][j][0]=sum[i&1][j][1]=sum[i&1][j][2]=0;
		for(int j=l[i];j<=r[i];j++)
		{
			ll tmp=0;
			if(j>0)tmp=sum[(i-1)&1][j-1][0]*(mo[j]!=0)+sum[(i-1)&1][j-1][1]*(mo[j]!=1)+sum[(i-1)&1][j-1][2]*(mo[j]!=2);
			// cout<<tmp<<endl;
			tmp=(tmp%mod+mod)%mod;
			dp[i&1][j]=(dp[i&1][j]+tmp)%mod;
			sum[i&1][j][mo[j]]=(sum[i&1][j][mo[j]]+dp[i&1][j])%mod;
			// cout<<i<<" "<<j<<" "<<dp[i&1][j]<<endl;
		}
		for(int j=l[i]+1;j<=r[i];j++)
		{
			sum[i&1][j][0]=(sum[i&1][j-1][0]+sum[i&1][j][0])%mod;
			sum[i&1][j][1]=(sum[i&1][j-1][1]+sum[i&1][j][1])%mod;
			sum[i&1][j][2]=(sum[i&1][j-1][2]+sum[i&1][j][2])%mod;
		}
	}
	ll ans=0;
	for(int i=l[n];i<=r[n];i++)ans=(ans+dp[n&1][i])%mod;
	cout<<ans<<endl;
	return 0;
}
/*
0 0 0
0 1 1
0 2 2
0 3 2
0 4 3
1 0 0
1 1 0
1 2 1
1 3 3
1 4 4
8



*/

观察可得:\(a_{i+1}-a_i>0\)
\(a_i\not \equiv a_{i+1} \mod 3\)
考虑差分,差分后有\(n\)
其中第一位\(b_0\)可以为\(0,1,2\)
其他的\(b_i\in {1,2}\)且由于\(a_n<=m\)\(\sum_{i=0}^{n-1}b_i<=m\)
我们可以枚举\(1或2\),枚举一个确定另一个数量,设\(b_0=i\),假设枚举\(j\)\(2\),则\(\sum b=n-1-j+2j+i=n+j-1+i<=m\)
每三个数出现一次\(\mod 3=0\)所以可以插入的\(3\)的个数最多为\(\lfloor{\frac{m-(n+j-1+i)}{3}}\rfloor\),所以答案为枚举\(2\)的方案乘上\(3\)的方案,\(3\)的方案数可以插空,一共\(n-1\)个空,注意可以一个空插多个,即为\(C_{n+cnt-1}^{n-1}\),所有\(ans=\sum_{i=0}^2\sum_{j=0}^{n-1}C_{n-1}^jC_{n+cnt_3-1}^{cnt_3-1}\)

注意要线性求阶乘逆元,即为\(\frac{1}{(i+1)!}\times (i+1)\),\(inv_{i}=inv_{i+1}\times (i+1)\)

点击查看代码
#include <bits/stdc++.h>
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define ll long long
// #define endl '\n'
#define pii pair<int,int>
#define ull unsigned long long
#define pb push_back
#define ts cout<<"----------------"<<endl;
#define bs bitset<65>
using namespace std;
const int mod=998244353,N=2e7+5;
int n,m;
int jie[N],inv[N],s[N];
inline int qpow(int a,int b)
{
	int ans=1;
	while(b)
	{
		if(b&1)ans=1ll*ans*a%mod;
		a=1ll*a*a%mod;
		b>>=1;
	}
	return ans;
}
inline int C(int n,int m)
{
	if(n<m)return 0;
	// if(!m)return 1;
	return 1ll*jie[n]*inv[n-m]%mod*inv[m]%mod;
}
int main()
{
	speed();
	// freopen("in.in","r",stdin);
	// freopen("out.out","w",stdout);
	cin>>n>>m;
	jie[0]=1;inv[0]=1;s[0]=1;
	for(int i=1;i<=2*m;i=-~i)
	{
		jie[i]=1ll*jie[i-1]*i%mod;
	}
	inv[2*m]=qpow(jie[2*m],mod-2);
	for(int i=2*m-1;i>=1;i--)
	{
		inv[i]=1ll*inv[i+1]*(i+1)%mod;
	}
	for(int i=1;i<=m;i++)
	{
		s[i]=(s[i-1]+C(n+i-1,n-1))%mod;
	}
	ll ans=0;
	for(int i=0;i<=2;i++)
	{
		for(int j=0;j+i<=m-n+1&&j<n;j++)
			ans=(ans+1ll*C(n-1,j)*s[(m-n-j-i+1)/3]%mod)%mod;
	}
	cout<<ans;
	return 0;	
}
/*
0 0 0
0 1 1
0 2 2
0 3 2
0 4 3
1 0 0
1 1 0
1 2 1
1 3 3
1 4 4
8



*/

T4

题目

image

后记

9G拉着我写线段树2,被硬控了,乐
易错:因为有加和乘法两种操作,先乘法后加,用乘法\(lz\)传给儿子的乘法以及加法\(lz\)标记,还有,为了避免顺序搞乱,\(pushdown\)放最上面

点击查看代码
#include <bits/stdc++.h>
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define ll long long
// #define endl '\n'
#define pii pair<int,int>
#define ull unsigned long long
#define pb push_back
#define lid (rt<<1)
#define rid (rt<<1|1)
#define ts cout<<"----------------"<<endl;
#define bs bitset<65>
using namespace std;
const int N = 1e5+5;
int n,q,mod,a[N];
struct
{
	int l,r;ll lzsum,lzmul,w;
}st[N<<3];
struct SegTree
{
	inline void pu(int rt)
	{
		st[rt].w=(st[lid].w+st[rid].w)%mod;
	}
	inline void pdsum(int rt)
	{
		if(st[rt].lzsum)
		{
			ll lz=st[rt].lzsum;st[rt].lzsum=0;
			(st[lid].lzsum+=lz)%=mod;
			(st[rid].lzsum+=lz)%=mod;
			(st[lid].w+=lz*(st[lid].r-st[lid].l+1)%mod)%=mod;
			(st[rid].w+=lz*(st[rid].r-st[rid].l+1)%mod)%=mod;
		}
	}
	inline void pdmul(int rt)
	{
		// cout<<st[rt].lzmul<<endl;
		if(st[rt].lzmul!=1)
		{
			ll lz=st[rt].lzmul;st[rt].lzmul=1;
			(st[lid].lzmul*=lz)%=mod;
			(st[rid].lzmul*=lz)%=mod;
			(st[lid].lzsum*=lz)%=mod;
			(st[rid].lzsum*=lz)%=mod;
			(st[lid].w*=lz)%=mod;
			(st[rid].w*=lz)%=mod;
		}
	}	
	inline void build(int rt,int l,int r) 
	{
		st[rt].l=l;st[rt].r=r;
		st[rt].lzmul=1;
		if(l==r)
		{
			st[rt].w=a[l];return;
		}
		int mid=l+r>>1;
		build(lid,l,mid);build(rid,mid+1,r);
		pu(rt);
	}
	inline void updatesum(int rt,int l,int r,ll v)
	{
		pdmul(rt);pdsum(rt);
		if(l<=st[rt].l&&st[rt].r<=r)
		{
			st[rt].w=(st[rt].w+v*(st[rt].r-st[rt].l+1)%mod)%mod;
			st[rt].lzsum=(st[rt].lzsum+v)%mod;return;
		}
		int mid=(st[rt].l+st[rt].r)>>1;
		
		if(l<=mid)updatesum(lid,l,r,v);
		if(r>mid)updatesum(rid,l,r,v);
		pu(rt);
	}
	inline void updatemul(int rt,int l,int r,ll v)
	{
		pdmul(rt);pdsum(rt);
		if(l<=st[rt].l&&st[rt].r<=r)
		{
			st[rt].w=st[rt].w*v%mod;
			st[rt].lzmul=(st[rt].lzmul*v)%mod;

			return;
		}
		int mid=(st[rt].l+st[rt].r)>>1;
		
		if(l<=mid)updatemul(lid,l,r,v);
		if(r>mid)updatemul(rid,l,r,v);
		pu(rt);
	}
	inline ll query(int rt,int l,int r)
	{
		// cout<<rt<<" "<<st[rt].l<<" "<<st[rt].r<<endl;
		pdmul(rt);pdsum(rt);
		if(l<=st[rt].l&&st[rt].r<=r)
		{
			return st[rt].w;
		}
		int mid=(st[rt].l+st[rt].r)>>1;
		
		ll ans=0;
		if(l<=mid)ans=(ans+query(lid,l,r))%mod;
		if(r>mid)ans=(ans+query(rid,l,r))%mod;
		// pushup(rt);
		return ans;
	}
}T;
int main()
{
	speed();
	// freopen("in.in","r",stdin);
	// freopen("out.out","w",stdout);
	cin>>n>>q>>mod;
	for(int i=1;i<=n;i++)cin>>a[i];
	int op,x,y,k;
	T.build(1,1,n);
	// cout<<T.query(1,1,n)<<endl;
	while(q--)
	{
		cin>>op;
		if(op==1)
		{
			cin>>x>>y>>k;
			T.updatemul(1,x,y,k%mod);
		}else if(op==2)
		{
			cin>>x>>y>>k;
			T.updatesum(1,x,y,k%mod);
		}else
		{
			cin>>x>>y;
			cout<<T.query(1,x,y)<<endl;
		}
	}
	return 0;
}
posted @ 2024-08-20 11:08  wlesq  阅读(11)  评论(0编辑  收藏  举报