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砖块, 数字,甜圈题解的主要内容,如果未能解决你的问题,请参考以下文章