CSP-S模拟7

由于昨天难了所以就丢了四个套路题上来呗

T1 序列问题

三维偏序类的转移,其中两位偏序时第三维一定偏序,于是可以变成一个log

点击查看代码


#include <bits/stdc++.h>
typedef long long ll;typedef unsigned long long ull; typedef double db;typedef long double ldb;
#define fre(x) freopen(#x ".in","r",stdin),freopen(#x ".out","w",stdout)
#define Rep(i,a,b) for(int i=a;i<=b;++i) 
#define Dwn(i,a,b) for(int i=a;i>=b;--i)
#define pii pair<int,int>
#define mair make_pair
#define fir first
#define sec second
using namespace std;

const int maxn=5e5+10,INF=1e9+20051107;

int f[maxn];
int n,a[maxn],b[maxn];
int id[maxn];

bool cmp(const int &x,const int &y){if(b[x]==b[y])return a[x]<a[y];else return b[x]<b[y];}

struct BIT{
	#define lowbit(x) (x&-x)
	int c[maxn];
	void Add(int x,int d){++x;for(;x<=n+1;x+=lowbit(x))c[x]=max(c[x],d);}
	int Query(int x){++x;int res=0;for(;x;x-=lowbit(x))res=max(res,c[x]);return res;}
}T;

void solve(){
	fre(sequence);
	cin>>n;
	Rep(i,1,n)cin>>a[i],id[i]=i;
	Rep(i,1,n)b[i]=i-a[i];
	int len=0;f[0]=0;
	sort(id+1,id+n+1,cmp);
	Rep(t,1,n){
		int i=id[t];
		if(a[i]<=i){
			f[i]=T.Query(a[i]-1)+1;
			T.Add(a[i],f[i]);
		}
	}
	Rep(i,1,n)len=max(len,f[i]);
	cout<<len<<"\n";
}

int main (){ ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);return solve(),0; }


T2 钱仓

套路断环成链,由于 \(x^2+y^2 \leq (x+y)^2\) ,所以移动路线一定不发生包含,选择一个起点,维护冗余的队列,每次贪心从队首取就行。

点击查看代码


#include <bits/stdc++.h>
typedef long long ll;typedef unsigned long long ull; typedef double db;typedef long double ldb;
#define fre(x) freopen(#x ".in","r",stdin),freopen(#x ".out","w",stdout)
#define Rep(i,a,b) for(int i=a;i<=b;++i) 
#define Dwn(i,a,b) for(int i=a;i>=b;--i)
#define pii pair<int,int>
#define mair make_pair
#define fir first
#define sec second
#define int ll
using namespace std;

const int maxn=2e5+10,INF=1e17;

int n,a[maxn];
int ans,nxt;
pii tmp[maxn];
int tl,tr;

bool Sol(int l,int r){
	int tl=1,tr=0;ans=0;
	Rep(i,l,r){
		if(a[i]>0)tmp[++tr]=mair(a[i],i);
		while(tl<=tr && tmp[tl].fir==0)++tl;
		if(tl<=tr && tmp[tl].fir>0)ans+=(i-tmp[tl].sec)*(i-tmp[tl].sec),--tmp[tl].fir;
		else return nxt=i,false;
	}
	return true;
}

void solve(){fre(barn);
	cin>>n;
	Rep(i,1,n)cin>>a[i],a[i+n]=a[i];
	Rep(i,1,n+1){
		if(a[i] && a[i-1]==0){
			if(Sol(i,i+n-1))return cout<<ans<<"\n",void();
			else i=nxt;
		}
	}
}

#undef int 
int main (){ ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);return solve(),0; }

T3 自然数

发现加数可能并不是很好做,于是可以搞删数,考虑套路线段树,叶子节点i表示当前左界到i的mex,每次把左界删掉,那么从它到它下一次出现之前的位置,mex都一定不大于它,区间覆盖取min即可,无脑吉司机也行,但是由于mex有单调性,所以直接在线段树上二分覆盖就行

点击查看代码


#include <bits/stdc++.h>
typedef long long ll;typedef unsigned long long ull; typedef double db;typedef long double ldb;
#define fre(x) freopen(#x ".in","r",stdin),freopen(#x ".out","w",stdout)
#define Rep(i,a,b) for(int i=a;i<=b;++i) 
#define Dwn(i,a,b) for(int i=a;i>=b;--i)
#define pii pair<int,int>
#define mair make_pair
#define fir first
#define sec second
using namespace std;

const int maxn=2e5+10;

int n,a[maxn],mex[maxn];
ll ans;

struct MEX{
	int vec[maxn],mex;
	void Add(int x){++vec[x];while(vec[mex])++mex;}
}E;
struct Seg{
	struct Tree{int mini,lazy;ll sum;}tr[maxn<<2];
	void Pushup(int rt){
		tr[rt].mini=min(tr[rt<<1].mini,tr[rt<<1|1].mini),
		tr[rt].sum=tr[rt<<1].sum+tr[rt<<1|1].sum;
	}
	void Build(int rt,int l,int r){
		tr[rt].lazy=-1;
		if(l==r)return tr[rt].mini=tr[rt].sum=mex[l],void();
		int mid=(l+r)>>1;
		Build(rt<<1,l,mid),Build(rt<<1|1,mid+1,r);
		Pushup(rt);
	}
	void Update(int rt,int l,int r,int w){
		tr[rt].mini=tr[rt].lazy=w;
		tr[rt].sum=1LL*(r-l+1)*w;
	}
	void Pushdown(int rt,int l,int r){
		if(tr[rt].lazy==-1)return;
		int mid=(l+r)>>1;
		Update(rt<<1,l,mid,tr[rt].lazy);
		Update(rt<<1|1,mid+1,r,tr[rt].lazy);
		tr[rt].lazy=-1;
	}
	void Modify(int rt,int l,int r,int s,int t,int w){
		if(l==r)return tr[rt].sum=tr[rt].mini=min(tr[rt].mini,w),void();
		int mid=(l+r)>>1;
		Pushdown(rt,l,r);
		if(s<=l && t>=r){
			if(tr[rt<<1|1].mini>=w)Update(rt<<1|1,mid+1,r,w),Modify(rt<<1,l,mid,s,t,w);
			else Modify(rt<<1|1,mid+1,r,s,t,w);
			return Pushup(rt);
		}
		if(s<=mid)Modify(rt<<1,l,mid,s,t,w);
		if(t>mid)Modify(rt<<1|1,mid+1,r,s,t,w);
		Pushup(rt);
	}
	ll Query(int rt,int l,int r,int s,int t){
		if(s<=l && t>=r)return tr[rt].sum;
		int mid=(l+r)>>1;ll res=0;
		Pushdown(rt,l,r);
		if(s<=mid)res+=Query(rt<<1,l,mid,s,t);
		if(t>mid)res+=Query(rt<<1|1,mid+1,r,s,t);
		return res;
	}
}T;

int nxt[maxn],last[maxn];

void solve(){fre(mex);
	cin>>n;
	Rep(i,1,n)cin>>a[i];
	Rep(i,1,n){ if(a[i]<=n)E.Add(a[i]); mex[i]=E.mex;last[i]=n+1; }
	last[0]=n+1;
	Dwn(i,n,1){
		if(a[i]<=n){
			nxt[i]=last[a[i]];
			last[a[i]]=i;
		}
	}
	T.Build(1,1,n);
	Rep(i,1,n){
		ans+=T.Query(1,1,n,i,n);
		if(a[i]<=n) T.Modify(1,1,n,i+1,nxt[i]-1,a[i]);
	}
	cout<<ans<<"\n";
}

int main (){ ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);return solve(),0; }

T4 环路

甚至我之前做过原题,但是由于根本没有把柿子写出来,没反应过来,一种分治套路

点击查看代码


#include <bits/stdc++.h>
typedef long long ll;typedef unsigned long long ull; typedef double db;typedef long double ldb;
#define fre(x) freopen(#x ".in","r",stdin),freopen(#x ".out","w",stdout)
#define Rep(i,a,b) for(int i=a;i<=b;++i) 
#define Dwn(i,a,b) for(int i=a;i>=b;--i)
#define pii pair<int,int>
#define mair make_pair
#define fir first
#define sec second
using namespace std;

const int maxn=1e2+10,maxM=1e6+10;

int Mod,n,K;
ll ans;

int prime[maxM],cnt;
int vis[maxM];


struct Matrix{
	int a[maxn][maxn];
	Matrix(){memset(a,0,sizeof(a));}
	void Clear(){memset(a,0,sizeof(a));}
	void Init(){Rep(i,1,n)a[i][i]=1;}
	friend Matrix operator * (const Matrix &x,const Matrix &y){
		Matrix z;
		Rep(i,1,n)Rep(k,1,n)
		{ int r=x.a[i][k];  Rep(j,1,n)z.a[i][j]=(z.a[i][j]+1LL*r*y.a[k][j])%Mod; }
		return z;
	}
	Matrix Pow(int p){
		Matrix res,base=(*this);res.Init();
		while(p){if(p&1)res=res*base;p>>=1;base=base*base;}
		return res;
	}
	friend Matrix operator + (const Matrix &x,const Matrix &y){
		Matrix z;
		Rep(i,1,n)Rep(j,1,n)z.a[i][j]=(x.a[i][j]+y.a[i][j])%Mod;
		return z;
	}
	void operator += (const Matrix &x){ Rep(i,1,n)Rep(j,1,n)a[i][j]=(a[i][j]+x.a[i][j])%Mod; } 

	void Print(){Rep(i,1,n){ Rep(j,1,n)cerr<<a[i][j]%Mod<<" ";cerr<<"\n";}cerr<<"\n"; }
	void Calc(){ Rep(i,1,n)ans+=a[i][i];ans%=Mod; }
}F,G;

char s[maxn];

Matrix Calc(int x){
	if(x==1)return F;
	int mid=x>>1;
	Matrix res=Calc(mid),base=F.Pow(mid);
	if(x&1)return (res+(res*base)+F.Pow(x));
	else return res+(res*base);
}

void solve(){
	fre(tour);
	cin>>n;
	Rep(i,1,n){ cin>>(s+1); Rep(j,1,n)F.a[i][j]=(s[j]=='Y'); }
	cin>>K>>Mod;
	if(K==1)return cout<<0<<"\n",void();
	Calc(K-1).Calc();
	cout<<ans<<"\n";
}

int main (){ ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);return solve(),0; }

posted @ 2022-09-20 16:41  Delov  阅读(47)  评论(0编辑  收藏  举报