11.21 比赛总结

100+10+10+100,rk2。

T1 图

简单题,\(bitset\) 即可。时间复杂度 \(O(\frac{n^2m}{\omega})\)

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=10005;
int n,m,ans;string st;
bitset<N>ed[N],s,t,k;
signed main(){
	freopen("a.in","r",stdin);
	freopen("a.out","w",stdout);
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	cin>>n>>m;
	while(m--){
		cin>>st;
		for(int i=0;i<n;i++){
			s[i]=(st[i]=='2');
			t[i]=(st[i]=='1');
			k[i]=(st[i]=='3');
		}for(int i=0;i<n;i++){
			if(s[i]) ed[i+1]^=t|k;
			if(t[i]) ed[i+1]^=s|k;
			if(k[i]) ed[i+1]^=s|t|k;
		}for(int i=0;i<n;i++)
			s[i]=t[i]=k[i]=0;
	}for(int i=1;i<=n;i++)
		for(int j=0;j<n;j++)
			ans+=(i-1!=j)*ed[i][j];
	cout<<ans/2;
	return 0;
}

T2 序列

考虑每个位置赋值只能进行一次,直接将赋值转化为加法;同一位置上的加法肯定先加大后加小,那么 \(g_{i,j}\) 的贡献就是给原序列 \(\times \frac{g_{i,j}+a'_i}{a'_i}\),然后 \(a'_i\gets a'_i+g_{i,j}\),这样就将加法转化为乘法。最后前缀积即可。

#include<bits/stdc++.h>
#define db double
#define int long long
using namespace std;
const int N=1e5+5;
const int p=1e9+7;
int qpow(int x,int y){
	int re=1;
	while(y){
		if(y&1) re=re*x%p;
		x=x*x%p,y>>=1;
	}return re;
}int n,m,k,a[N],nw;
vector<int>g[N];int mx[N];
struct chg{int x,y;}ly[N];
int cmp(chg x,chg y){
	return (db)x.x*y.y>(db)y.x*x.y;
}int cmp1(int x,int y){
	return x>y;
}signed main(){
	freopen("b.in","r",stdin);
	freopen("b.out","w",stdout);
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	cin>>n>>m,nw=1;
	for(int i=1;i<=n;i++)
		cin>>a[i],nw=nw*a[i]%p;
	for(int i=1;i<=m;i++){
		int opt,x,y;cin>>opt>>x>>y;
		if(opt==1) mx[x]=max(mx[x],y);
		if(opt==2) g[x].push_back(y);
		if(opt==3) ly[++k]={y,1};
	}for(int i=1;i<=n;i++){
		if(!g[i].size()&&mx[i]<=a[i]) continue;
		if(mx[i]>a[i])
			g[i].push_back(mx[i]-a[i]);
		sort(g[i].begin(),g[i].end(),cmp1);
		int lyh=a[i];
		for(auto x:g[i])
			ly[++k]={lyh+x,lyh},lyh+=x;
	}sort(ly+1,ly+k+1,cmp);
	ly[0].x=ly[0].y=1;
	for(int i=0;i<=m;i++){
		if(i>k){cout<<nw<<" ";continue;}
		nw=nw*ly[i].x%p*qpow(ly[i].y,p-2)%p;
		cout<<nw<<" ";
	}return 0;
}

T3 树

大离谱题,每个人的 \(AC\) 代码都可以在一组手造数据上跑出不一样的风采,输出 \(n^{2d}\) 能得 \(90pts\)……题解没看懂,就贴代码了。

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+5;
const int p=1e9+7;
struct cat6{
	int xzz[2][2];
	cat6(){memset(xzz,0,sizeof(xzz));}
}a,b;vector<int>g[N];
int n,k,f1[N],f2[N],g1[N];
int m,g2[N],sr[N][2],s[N];
cat6 operator*(cat6 x,cat6 y){
	cat6 z;
	for(int i=0;i<2;i++) for(int j=0;j<2;j++) for(int l=0;l<2;l++)
		z.xzz[i][j]=(z.xzz[i][j]+x.xzz[i][l]*y.xzz[l][j])%p;
	return z;
}cat6 qpow(cat6 x,int y){
	cat6 re;
	re.xzz[0][0]=re.xzz[1][1]=1;
	while(y){
		if(y&1) re=re*x;
		x=x*x,y>>=1;
	}return re;
}void dfs1(int x,int fa){
	for(auto y:g[x]) if(y!=fa)
		dfs1(y,x),s[x]+=!f1[y],sr[x][f1[y]]+=g1[y];
	f1[x]=(s[x]>0);
	if(!s[x]) g1[x]=sr[x][1]+1;
	if(s[x]==1) g1[x]=sr[x][0];
}void dfs2(int x,int fa){
	m+=(!f1[x]);
	g2[x]=g1[x],f2[x]=f1[x];
	for(int y:g[x]){
		if(y==fa) continue;
		int sx=s[x],fx=f1[x],gx=g1[x];
		int szx=sr[x][0],sox=sr[x][1];
		int sy=s[y],fy=f1[y],gy=g1[y];
		int szy=sr[y][0],soy=sr[y][1];
		s[x]-=!f1[y],f1[x]=(s[x]>0);
		sr[x][f1[y]]-=g1[y];
		if(s[x]==1) g1[x]=sr[x][0];
		if(!s[x]) g1[x]=sr[x][1]+1;
		if(s[x]>1) g1[x]=0;
		f1[y]|=!f1[x],s[y]+=!f1[x];
		sr[y][f1[x]]+=g1[x];
		if(s[y]==1) g1[y]=sr[y][0];
		if(!s[y]) g1[y]=sr[y][1]+1;
		if(s[y]>1) g1[y]=0;dfs2(y,x);
		s[x]=sx,f1[x]=fx,g1[x]=gx;
		sr[x][0]=szx,sr[x][1]=sox;
		s[y]=sy,f1[y]=fy,g1[y]=gy;
		sr[y][0]=szy,sr[y][1]=soy;
	}
}signed main(){
	freopen("c.in","r",stdin);
	freopen("c.out","w",stdout);
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	cin>>n>>k;int ans=0;
	for(int i=1,x,y;i<n;i++){
		cin>>x>>y;
		g[x].push_back(y);
		g[y].push_back(x);
	}dfs1(1,0),dfs2(1,0);
	for(int i=1;i<=n;i++){
		if(!f2[i]){
			b.xzz[1][0]=(b.xzz[1][0]+n)%p;
			b.xzz[0][0]=(b.xzz[0][0]+n-g2[i])%p;
			b.xzz[0][1]=(b.xzz[0][1]+g2[i])%p;
		}if(f2[i]==1){
			b.xzz[0][0]=(b.xzz[0][0]+g2[i])%p;
			b.xzz[0][1]=(b.xzz[0][1]+n-g2[i])%p;
			b.xzz[1][1]=(b.xzz[1][1]+n)%p;
		}
	}a.xzz[0][0]=m,a.xzz[0][1]=n-m;
	a=a*qpow(b,k-1);
	int ly=a.xzz[0][0],wz=a.xzz[0][1];
	if(f1[1]) cout<<((n-g2[1])*ly%p+n*wz%p+p+p)%p;
	else cout<<g2[1]*ly%p;
	return 0;
}

D 字符串

个人感觉难度应该放 \(B/C\)

容易发现相邻点对只有 \(100\) 种情况,且种内填充字符数相同。用线段树维护相邻点对即可。时间复杂度 \(O(k^2m\log n+k^2n)\)

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5,M=8e5+5;
int n,m,k,sm[M][10][10],rs=-1;string s;
int tmp[10][10],kmp[10][10],lc[M],rc[M],fl[M];
void push_up(int x){
	for(int i=0;i<k;i++) for(int j=0;j<k;j++)
		sm[x][i][j]=sm[x*2][i][j]+sm[x*2+1][i][j];
	lc[x]=lc[x*2],rc[x]=rc[x*2+1];
	sm[x][rc[x*2]][lc[x*2+1]]++;
}void pd(int x,int c){
	for(int i=0;i<k;i++)
		for(int j=0;j<k;j++)
			tmp[i][j]=sm[x][i][j];
	for(int i=0;i<k;i++) for(int j=0;j<k;j++)
		sm[x][(i+c)%k][(j+c)%k]=tmp[i][j],tmp[i][j]=0;
	lc[x]=(lc[x]+c)%k,fl[x]=(fl[x]+c)%k;
	rc[x]=(rc[x]+c)%k;
}void push_down(int x){
	if(!fl[x]) return;
	pd(x*2+1,fl[x]);
	pd(x*2,fl[x]),fl[x]=0;
}void add(int x){
	for(int i=0;i<k;i++)
		for(int j=0;j<k;j++)
			kmp[i][j]+=sm[x][i][j];
	if(~rs) kmp[rs][lc[x]]++;
	rs=rc[x];
}void build(int x,int l,int r){
	if(l==r){
		lc[x]=rc[x]=s[l]-'a';
		return;
	}int mid=(l+r)/2;
	build(x*2,l,mid);
	build(x*2+1,mid+1,r);
	push_up(x);
}void chg(int x,int l,int r,int L,int R,int c){
	if(L<=l&&r<=R)
		return pd(x,c),void();
	push_down(x);
	int mid=(l+r)/2;
	if(L<=mid) chg(x*2,l,mid,L,R,c);
	if(R>mid) chg(x*2+1,mid+1,r,L,R,c);
	push_up(x);
}void gadd(int x,int l,int r,int L,int R){
	if(L<=l&&r<=R)
		return add(x),void();
	push_down(x);
	int mid=(l+r)/2;
	if(L<=mid) gadd(x*2,l,mid,L,R);
	if(R>mid) gadd(x*2+1,mid+1,r,L,R); 
}int gch(int x,int l,int r,int v){
	if(l==r) return lc[x];
	int mid=(l+r)/2;push_down(x);
	if(v<=mid) return gch(x*2,l,mid,v);
	return gch(x*2+1,mid+1,r,v);
}signed main(){
	freopen("d.in","r",stdin);
	freopen("d.out","w",stdout);
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	cin>>n>>m>>k>>s;
	s=" "+s,build(1,1,n);
	while(m--){
		int opt;cin>>opt;
		if(opt==1){
			int l,r,c;cin>>l>>r>>c;
			chg(1,1,n,l,r,c);continue;
		}int l,r;cin>>l>>r>>s;
		gadd(1,1,n,l,r);int ans=0;
		for(int i=0;i<k;i++)
			for(int j=0;j<k;j++){
				int ln=((i==j)?k:(j-i+k)%k);
				ans+=kmp[s[i]-'a'][s[j]-'a']*ln;
				kmp[s[i]-'a'][s[j]-'a']=0;
			}
		int ch=gch(1,1,n,l);
		for(int i=0;i<k;i++)
			if(s[i]-'a'==ch) ans+=i;
		ch=gch(1,1,n,r);
		for(int i=0;i<k;i++)
			if(s[i]-'a'==ch) ans+=k-i;
		cout<<ans/k<<"\n",rs=-1;
	}return 0;
}
posted @ 2024-11-21 21:36  长安一片月_22  阅读(9)  评论(0编辑  收藏  举报