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


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


    T1

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

    ( ext{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

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

    ( ext{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
    ",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 imes g(n-1)+2 imes g(n-2)-g(n-3))

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

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

    [A= egin{bmatrix} 2&2&-1\ 1&0&0\ 0&1&0 end{bmatrix}, G_n= egin{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_{Tsubseteq S}g_{sum_{xin T}x}) ,得到:

    [F_{S}=sum_{Tsubseteq S}G_{sum_{xin T}x} ]

    则:

    [egin{aligned} F_{Scup{a}}&=F_{S}+sum_{Tsubseteq S}G_{a+sum_{xin T}x}\ &=F_S+sum_{Tsubseteq S}A_aG_{sum_{xin T}x}\ &=F_S+A^aF_S\ &=(I+A^a)F_S end{aligned} ]

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

    [egin{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}^rsum_{j=l}^rprod_{k=i}^jB_{a_k}) 即可。

    ( ext{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
    ",(res.ans*G).A[1][1]);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    ckeditor+粘贴word
    java+批量下载大文件
    链接批量下载文件
    java+大文件上传解决方案
    php+提高大文件上传速度
    富文本粘贴word文档内容图片处理
    软件开发工具(三)——理论与开发过程
    c结构体里的数组与指针
    Java解析Property文件
    怎样高速编译mediatekoperator以下代码
  • 原文地址:https://www.cnblogs.com/syc233/p/13879437.html
Copyright © 2020-2023  润新知