Loading

测试「2020牛客NOIP赛前集训营-提高组(第四场)」

考试时间在周末,估计没几个人认真考,于是混了个rk13。


T1

枚举 \(V\) 的位置,判断前后是否合法。

\(\text{Code}:\)

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long lxl;
const int maxn=1e5+5;

template <typename T>
inline void read(T &x)
{
	x=0;T f=1;char ch=getchar();
	while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
	x*=f;
}

int n;
char s[maxn];
int w[26];
bool chk[2][maxn];

int main()
{
#ifndef ONLINE_JUDGE
	freopen("A.in","r",stdin);
	freopen("A.out","w",stdout);
#endif
	int T;read(T);
	while(T--)
	{
		for(int i=0;i<26;++i) read(w[i]);
		scanf(" %s",s+1);
		n=strlen(s+1);
		if(!((w[s[n]-'a']>>1)&1)) {puts("No");continue;}
		for(int i=1;i<=n;++i)
		{
			chk[0][i]=chk[0][i-1];
			int c=s[i]-'a';
			if(w[c]==4) chk[0][i]=true;
		}
		for(int i=n;i>=1;--i)
		{
			chk[1][i]=chk[1][i+1];
			int c=s[i]-'a';
			if(w[c]==4) chk[1][i]=true;
		}
		bool flag=false;
		for(int i=2;i<n;++i)
		{
			int c=s[i]-'a';
			if(((w[c]>>2)&1)&&!chk[0][i-1]&&!chk[1][i+1]&&((w[s[i-1]-'a']>>1)&1))
			{
				flag=true;
				break;
			}
		}
		puts(flag?"Yes":"No");
	}
	return 0;
}

T2

考试的时候没多想,看到数据范围 \(2\cdot10^5\) 直接上平衡树模拟了。

\(\text{Code}:\)

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#define Rint register int
#define INF 0x3f3f3f3f
using namespace std;
typedef long long lxl;
const int maxn=3e5+5;

template <typename T>
inline void read(T &x)
{
	x=0;T f=1;char ch=getchar();
	while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
	x*=f;
}

int n,m;

namespace Treap
{
	int tot,pool[maxn],top;
	int ch[maxn][2];
	lxl siz[maxn],cnt[maxn];
	int val[maxn],rnd[maxn];
	bool rev[maxn];
	inline int new_node()
	{
		int p=top?pool[top--]:++tot;
		ch[p][0]=ch[p][1]=0;
		siz[p]=cnt[p]=0;
		val[p]=rnd[p]=0;
		rev[p]=false;
		return p;
	}
	inline void reverse(int p)
	{
		swap(ch[p][0],ch[p][1]);
		rev[p]^=1;
	}
	inline void push_down(int p)
	{
		if(!rev[p]) return;
		reverse(ch[p][0]);
		reverse(ch[p][1]);
		rev[p]=0;
	}
	inline void update(int p)
	{
		siz[p]=siz[ch[p][0]]+siz[ch[p][1]]+cnt[p];
	}
	void split_rnk(int p,int k,int &x,int &y,int &z)
	{
		if(!p) return x=y=z=0,void();
		push_down(p);
		if(siz[ch[p][0]]>=k)
		{
			z=p;
			split_rnk(ch[p][0],k,x,y,ch[p][0]);
		}
		else if(siz[ch[p][0]]+cnt[p]<k)
		{
			x=p;
			split_rnk(ch[p][1],k-siz[ch[p][0]]-cnt[p],ch[p][1],y,z);
		}
		else
		{
			x=ch[p][0],y=p,z=ch[p][1];
			ch[p][0]=ch[p][1]=0;
		}
		update(p);
	}
	int merge(int a,int b)
	{
		if(!a||!b) return a|b;
		push_down(a),push_down(b);
		if(rnd[a]<rnd[b])
		{
			ch[a][1]=merge(ch[a][1],b);
			update(a);
			return a;
		}
		else
		{
			ch[b][0]=merge(a,ch[b][0]);
			update(b);
			return b;
		}
	}
	inline int new_node(int s,int c)
	{
		if(!s) return 0;
		int p=new_node();
		siz[p]=cnt[p]=s;
		val[p]=c;
		rnd[p]=rand();
		return p;
	}
	inline void erase(int &p)
	{
		if(!p) return;
		erase(ch[p][0]);
		erase(ch[p][1]);
		pool[++top]=p;
		p=0;
	}
	// inline void print(int p)
	// {
	// 	if(!p) return;
	// 	push_down(p);
	// 	print(ch[p][0]);
	// 	for(int i=1;i<=cnt[p];++i)
	// 		printf("%d ",val[p]);
	// 	print(ch[p][1]);
	// }
}
int rt[maxn];

int main()
{
#ifndef ONLINE_JUDGE
	freopen("B.in","r",stdin);
	freopen("B.out","w",stdout);
#endif
	read(n),read(m);
	char opt[5];
	int x,y,z;
	while(m--)
	{
		scanf(" %s",opt);
		read(x),read(y);
		if(opt[2]=='s')
		{
			read(z);
			rt[z]=Treap::merge(Treap::new_node(x,y),rt[z]);
		}
		else if(opt[2]=='p')
		{
			int a,b,c;
			Treap::split_rnk(rt[y],x,a,b,c);
			rt[y]=Treap::merge(Treap::new_node(Treap::siz[a]+Treap::cnt[b]-x,Treap::val[b]),c);
			printf("%d\n",Treap::val[b]);
			Treap::erase(a);
			Treap::erase(b);
		}
		else
		{
			Treap::reverse(rt[x]);
			rt[y]=Treap::merge(rt[x],rt[y]);
			rt[x]=0;
		}
		// puts("---");
		// for(int i=1;i<=n;++i)
		// 	Treap::print(rt[i]),puts("");
		// puts("---");
	}
	return 0;
}

T3

\(g(n)=fib(n)^2\) ,则由数理基础可以发现:\(g(n)=2\times g(n-1)+2\times g(n-2)-g(n-3)\)

于是 \(g(n)\) 可以矩阵递推:

\[\begin{bmatrix} g(n)\\ g(n-1)\\ g(n-2)\\ \end{bmatrix} = \begin{bmatrix} 2&2&-1\\ 1&0&0\\ 0&1&0 \end{bmatrix} \times \begin{bmatrix} g(n-1)\\ g(n-2)\\ g(n-3) \end{bmatrix} \]

\[A= \begin{bmatrix} 2&2&-1\\ 1&0&0\\ 0&1&0 \end{bmatrix}, G_n= \begin{bmatrix} g(n)\\ g(n-1)\\ g(n-2)\\ \end{bmatrix} \]

则有 \(G_n=A^nG_0\)

考虑如何通过矩阵递推求出 \(f_S\) ,将 \(f_S\) 向量化为 \(F_S\) 。由 \(f_S=\sum_{T\subseteq S}g_{\sum_{x\in T}x}\) ,得到:

\[F_{S}=\sum_{T\subseteq S}G_{\sum_{x\in T}x} \]

则:

\[\begin{aligned} F_{S\cup\{a\}}&=F_{S}+\sum_{T\subseteq S}G_{a+\sum_{x\in T}x}\\ &=F_S+\sum_{T\subseteq S}A_aG_{\sum_{x\in T}x}\\ &=F_S+A^aF_S\\ &=(I+A^a)F_S \end{aligned} \]

由定义可知:\(F_0=G_0\) 。令 \(B_a=I+A^a\) ,则:

\[\begin{aligned} S&=\{a_1,a_2,a_3,\cdots,a_n\}\\ F_S&=\prod_{i=1}^nB_{a_i}G_0 \end{aligned} \]

于是用线段树维护区间 \([l,r]\)\(\sum_{i=l}^r\sum_{j=l}^r\prod_{k=i}^jB_{a_k}\) 即可。

\(\text{Code}:\)

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#define Rint register int
#define INF 0x3f3f3f3f
using namespace std;
typedef long long lxl;
const int maxn=1e5+5;
const lxl mod=998244353;

template <typename T>
inline void read(T &x)
{
	x=0;T f=1;char ch=getchar();
	while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
	x*=f;
}

struct Matrix
{
	int A[5][5],N,M;
	Matrix(int N,int M):N(N),M(M){memset(A,0,sizeof(A));}
	Matrix(){}
	inline Matrix operator + (const Matrix &T)const
	{
		Matrix res=*this;
		for(int i=1;i<=N;++i)
			for(int j=1;j<=M;++j)
				(res.A[i][j]+=T.A[i][j])%=mod;
		return res;
	}
	inline Matrix operator * (const Matrix &T)const
	{
		Matrix res=Matrix(N,T.M);
		for(int i=1;i<=N;++i)
			for(int k=1;k<=M;++k)
				for(int j=1;j<=T.M;++j)
					(res.A[i][j]+=1ll*A[i][k]*T.A[k][j]%mod)%=mod;
		return res;
	}
	inline void print()
	{
		for(int i=1;i<=N;++i,puts(""))
			for(int j=1;j<=M;++j)
				printf("%d ",A[i][j]);
		puts("");
	}
}I,A[maxn],G;

struct node
{
	int l,r;
	Matrix sum,ans,lsum,rsum;
	node(int l,int r,Matrix sum=I,Matrix ans=I,Matrix lsum=I,Matrix rsum=I)
		:l(l),r(r),sum(sum),ans(ans),lsum(lsum),rsum(rsum){}
	node(){}
	inline node operator + (const node &T)const
	{
		node res(l,T.r);
		res.sum=sum*T.sum;
		res.ans=ans+T.ans+rsum*T.lsum;
		res.lsum=lsum+sum*T.lsum;
		res.rsum=rsum*T.sum+T.rsum;
		return res;
	}
};

int n,q,a[maxn];

namespace Segment_Tree
{
	node tree[maxn<<2];
	#define ls (p<<1)
	#define rs (p<<1|1)
	inline void set(int p,Matrix d)
	{
		tree[p].sum=tree[p].ans=tree[p].lsum=tree[p].rsum=d;
	}
	void build(int p,int l,int r)
	{
		tree[p]=node(l,r);
		if(l==r) return set(p,I+A[a[l]]),void();
		int mid=(l+r)>>1;
		build(ls,l,mid);
		build(rs,mid+1,r);
		tree[p]=tree[ls]+tree[rs];
	}
	void modify(int p,int ps,int d)
	{
		int l=tree[p].l,r=tree[p].r;
		if(l==r) return set(p,I+A[d]),void();
		int mid=(l+r)>>1;
		if(ps<=mid) modify(ls,ps,d);
		else modify(rs,ps,d);
		tree[p]=tree[ls]+tree[rs];
	}
	node query(int p,int L,int R)
	{
		int l=tree[p].l,r=tree[p].r;
		if(L<=l&&r<=R) return tree[p];
		int mid=(l+r)>>1;
		if(R<=mid) return query(ls,L,R);
		else if(L>mid) return query(rs,L,R);
		else return query(ls,L,R)+query(rs,L,R);
	}
}

int main()
{
#ifndef ONLINE_JUDGE
	freopen("C.in","r",stdin);
	freopen("C.out","w",stdout);
#endif
	read(n),read(q);
	for(int i=1;i<=n;++i) read(a[i]);
	I=Matrix(3,3);I.A[1][1]=I.A[2][2]=I.A[3][3]=1;
	A[1]=Matrix(3,3);
	A[1].A[1][1]=A[1].A[1][2]=2;A[1].A[1][3]=mod-1;
	A[1].A[2][1]=A[1].A[3][2]=1;
	for(int i=2;i<=1e5;++i)
		A[i]=A[i-1]*A[1];
	G=Matrix(3,1);G.A[1][1]=0;G.A[2][1]=G.A[3][1]=1;
	Segment_Tree::build(1,1,n);
	int opt,x,y;
	while(q--)
	{
		read(opt),read(x),read(y);
		if(opt==1) Segment_Tree::modify(1,x,y);
		else
		{
			node res=Segment_Tree::query(1,x,y);
			// res.ans.print();
			printf("%d\n",(res.ans*G).A[1][1]);
		}
	}
	return 0;
}
posted @ 2020-10-26 17:03  GoPoux  阅读(101)  评论(0编辑  收藏  举报