csp-s模拟测试61砖块, 数字,甜圈题解

Posted juve

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了csp-s模拟测试61砖块, 数字,甜圈题解相关的知识,希望对你有一定的参考价值。

题面:https://www.cnblogs.com/Juve/articles/11626350.html

砖块:

直接模拟即可,map统计被覆盖的次数

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
using namespace std;
const int MAXN=1005;
int n,k,len,a,b,x,y,ans=0;//a,b:xia,x,y:shang
char opt[MAXN];
map< pair<int,int>,int>m;
void workN(int &a,int &b,int &x,int &y)
	if(a==x)
		if(b==y) ++b,y+=k;
		else b=++y;
	else ++b,++y;
	for(int i=a;i<=x;++i)
		for(int j=b;j<=y;++j)
			pair<int,int>pa=make_pair(i,j);
			if(m.find(pa)!=m.end()) m[pa]++;
			else m[pa]=1;
			ans=max(ans,m[pa]);
		
	

void workS(int &a,int &b,int &x,int &y)
	if(a==x)
		if(b==y) --y,b-=k;
		else y=--b;
	else --b,--y;
	for(int i=a;i<=x;++i)
		for(int j=b;j<=y;++j)
			pair<int,int>pa=make_pair(i,j);
			if(m.find(pa)!=m.end()) m[pa]++;
			else m[pa]=1;
			ans=max(ans,m[pa]);
		
	

void workW(int &a,int &b,int &x,int &y)
	if(b==y)
		if(a==x) --x,a-=k;
		else x=--a;
	else--a,--x;
	for(int i=a;i<=x;++i)
		for(int j=b;j<=y;++j)
			pair<int,int>pa=make_pair(i,j);
			if(m.find(pa)!=m.end()) m[pa]++;
			else m[pa]=1;
			ans=max(ans,m[pa]);
		
	

void workE(int &a,int &b,int &x,int &y)
	if(b==y)
		if(a==x) ++a,x+=k;
		else a=++x;
	else ++x,++a;
	for(int i=a;i<=x;++i)
		for(int j=b;j<=y;++j)
			pair<int,int>pa=make_pair(i,j);
			if(m.find(pa)!=m.end()) m[pa]++;
			else m[pa]=1;
			ans=max(ans,m[pa]);
		
	

int main()
	scanf("%d",&n);
	while(n--)
		scanf("%d%s",&k,opt+1);
		len=strlen(opt+1);
		a=b=x=y=0;
		m.clear();
		m[make_pair(0,0)]=ans=1;
		for(int i=1;i<=len;++i)
			if(opt[i]==‘N‘) workN(a,b,x,y);
			else if(opt[i]==‘S‘) workS(a,b,x,y);
			else if(opt[i]==‘W‘) workW(a,b,x,y);
			else if(opt[i]==‘E‘) workE(a,b,x,y);
		
		if(a==x)
			for(int i=b;i<=y;++i) printf("%d ",a);
			puts("");
			for(int i=b;i<=y;++i) printf("%d ",i);
			puts("");
			printf("%d\\n",ans);
		else
			for(int i=a;i<=x;++i) printf("%d ",i);
			puts("");
			for(int i=a;i<=x;++i) printf("%d ",b);
			puts("");
			printf("%d\\n",ans);
		
	
	return 0;

数字:

甜圈:

考虑一种不完美的算法,对于每次修改,我们在线段树上区间加,最后统计叶节点的和是否为$\\frack*(k+1)2$,

但是会有顺序的影响,1+3+2也会被我们算为合法

为了排除顺序的影响,我们给它一个hash,每次区间加我们先让它乘上base,然后再加

这样就是一个支持区间加,区间乘的线段树

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ull unsigned long long
using namespace std;
const int base=31;
const int MAXN=200005;
int n,k,t;
ull tot;
struct node
	ull laz_add,laz_mul,sum;
	node()laz_add=sum=0,laz_mul=1;
tr[MAXN<<2];
void down(int k,int l,int r)
    int mid=(l+r)>>1;
    if(tr[k].laz_mul!=1)
        int mid=(l+r)>>1;
        tr[k<<1].sum*=tr[k].laz_mul;
        tr[k<<1|1].sum*=tr[k].laz_mul;
        tr[k<<1].laz_mul*=tr[k].laz_mul;
        tr[k<<1|1].laz_mul*=tr[k].laz_mul;
        tr[k<<1].laz_add*=tr[k].laz_mul;
        tr[k<<1|1].laz_add*=tr[k].laz_mul;
        tr[k].laz_mul=1;
    
    if(tr[k].laz_add!=0)
        tr[k<<1].sum+=(mid-l+1)*tr[k].laz_add;
        tr[k<<1|1].sum+=(r-mid)*tr[k].laz_add;
        tr[k<<1].laz_add+=tr[k].laz_add;
        tr[k<<1|1].laz_add+=tr[k].laz_add;
        tr[k].laz_add=0;
    

void update(int k,int l,int r,int opl,int opr,int val)
    if(opl<=l&&r<=opr)
    	(tr[k].sum*=base)+=(r-l+1)*val;
        tr[k].laz_mul*=base;
        (tr[k].laz_add*=base)+=val;
        return ;
    
    down(k,l,r);
    int mid=(l+r)>>1;
    if(opl<=mid) update(k<<1,l,mid,opl,opr,val);
    if(opr>mid) update(k<<1|1,mid+1,r,opl,opr,val);
    tr[k].sum=(tr[k<<1].sum+tr[k<<1|1].sum);

int query(int k,int l,int r)
	if(l==r)
		if(tr[k].sum==tot) return 1;
		else return 0;
	
	down(k,l,r);
	int mid=(l+r)>>1;
	return query(k<<1,l,mid)+query(k<<1|1,mid+1,r);

signed main()
	scanf("%d%d%d",&n,&k,&t);
	for(int i=1;i<=k;++i) tot=tot*base+i;
	while(t--)
		int l,r,x;
		scanf("%d%d%d",&l,&r,&x);
		update(1,1,n,l,r,x);
	
	printf("%d\\n",query(1,1,n));
	return 0;

另:区间加和区间乘的线段树板子:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define int long long
using namespace std;
const int MAXN=1e5+5;
int n,m,p,a[MAXN];
struct node
    int sum,laz_add,laz_mul;
tr[MAXN<<2];
void build(int k,int l,int r)
    tr[k].laz_add=0,tr[k].laz_mul=1;
    if(l==r)
        tr[k].sum=a[l]%p;
        return ;
    
    int mid=(l+r)>>1;
    build(k<<1,l,mid),build(k<<1|1,mid+1,r);
    tr[k].sum=(tr[k<<1].sum+tr[k<<1|1].sum)%p;

void down(int k,int l,int r)
    int mid=(l+r)>>1;
    if(tr[k].laz_mul!=1)
        int mid=(l+r)>>1;
        (tr[k<<1].sum*=tr[k].laz_mul%p)%=p;
        (tr[k<<1|1].sum*=tr[k].laz_mul%p)%=p;
        (tr[k<<1].laz_mul*=tr[k].laz_mul%p)%=p;
        (tr[k<<1|1].laz_mul*=tr[k].laz_mul%p)%=p;
        (tr[k<<1].laz_add*=tr[k].laz_mul%p)%=p;
        (tr[k<<1|1].laz_add*=tr[k].laz_mul%p)%=p;
        tr[k].laz_mul=1;
    
    if(tr[k].laz_add!=0)
        (tr[k<<1].sum+=(mid-l+1)*tr[k].laz_add%p)%=p;
        (tr[k<<1|1].sum+=(r-mid)*tr[k].laz_add%p)%=p;
        (tr[k<<1].laz_add+=tr[k].laz_add)%=p;
        (tr[k<<1|1].laz_add+=tr[k].laz_add)%=p;
        tr[k].laz_add=0;
    

void update_add(int k,int l,int r,int opl,int opr,int val)
    if(opl<=l&&r<=opr)
        (tr[k].sum+=(r-l+1)*val%p)%=p;
        (tr[k].laz_add+=val)%=p;
        return ;
    
    down(k,l,r);
    int mid=(l+r)>>1;
    if(opl<=mid) update_add(k<<1,l,mid,opl,opr,val);
    if(opr>mid) update_add(k<<1|1,mid+1,r,opl,opr,val);
    tr[k].sum=(tr[k<<1].sum+tr[k<<1|1].sum)%p;

void update_mul(int k,int l,int r,int opl,int opr,int val)
    if(opl<=l&&r<=opr)
        (tr[k].sum*=val%p)%=p;
        (tr[k].laz_mul*=val%p)%=p;
        (tr[k].laz_add*=val%p)%=p;
        return ;
    
    down(k,l,r);
    int mid=(l+r)>>1;
    if(opl<=mid) update_mul(k<<1,l,mid,opl,opr,val);
    if(opr>mid) update_mul(k<<1|1,mid+1,r,opl,opr,val);
    tr[k].sum=(tr[k<<1].sum+tr[k<<1|1].sum)%p;

int query(int k,int l,int r,int opl,int opr)
    if(opl<=l&&r<=opr) return tr[k].sum%p;
    down(k,l,r);
    int mid=(l+r)>>1,res=0;
    if(opl<=mid) (res+=query(k<<1,l,mid,opl,opr))%=p;
    if(opr>mid) (res+=query(k<<1|1,mid+1,r,opl,opr))%=p;
    return res;

signed main()
    //freopen("seq2.in","r",stdin);
    scanf("%lld%lld",&n,&p);
    for(int i=1;i<=n;++i) scanf("%lld",&a[i]);
    build(1,1,n);
    scanf("%lld",&m);
    for(int i=1,opt,t,g,c,tot=0;i<=m;++i)
        scanf("%lld%lld%lld",&opt,&t,&g);
        if(opt==1)
            scanf("%lld",&c);
            update_mul(1,1,n,t,g,c);
        
        else if(opt==2)
            scanf("%lld",&c);
            update_add(1,1,n,t,g,c);
        
        else
            printf("%lld\\n",query(1,1,n,t,g)%p);
        
    
    return 0;

 

以上是关于csp-s模拟测试61砖块, 数字,甜圈题解的主要内容,如果未能解决你的问题,请参考以下文章

CSP-S 模拟61

[考试反思]1006csp-s模拟测试61:休止

反省——关于csp-s模拟50

[CSP-S模拟测试59]题解

[CSP-S模拟测试53]题解

[CSP-S模拟测试74]题解