1 条题解
-
0
自动搬运
来自洛谷,原作者为

未来姚班zyl
欢迎加入粉丝团!https://www.luogu.com.cn/team/72518|AFO搬运于
2025-08-24 21:47:14,当前版本为作者最后更新于2024-05-30 09:16:54,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
很好的一道题,让我模拟赛没看 T2 T3。
题目大意
有一个 行的网格图,上面有 个僵尸。
你可以选择一行扔出一个坚果,坚果会沿着这行水平滚出。
如果撞到了一个僵尸,则坚果会改变运动方向,如果水平撞上,则如果在前 行,坚果就会向右下 方向滚出,否则向右上 方向滚出。如果是以斜着的方向撞上,则会在这两种方向中切换。然后,这个僵尸就被击倒了,并不会再出现在网格图上。
出题人要选一行扔出坚果,满足能击倒最多的僵尸的前提下编号最小。请你模拟 轮这样的操作,每轮输出扔出的行编号和击倒的僵尸数目。
题目分析
这种较为复杂的限制,往往用图论建模来描绘。
将每个点拆点,分为左上和左下两个点。然后连向往那个方向出发后会碰到的第一个点。很容易发现,图由若干条链构成。
如果一个僵尸被击倒,则相当于这个地方不会再改变方向。只需要将两条链在此处断开然后接到正确的位置。
考虑用平衡树维护这些链,map 维护每一行出发会碰到的第一个僵尸,称这些僵尸为关键僵尸,显然我们的链只需要维护最靠左端的关键僵尸。然后用线段树维护一下每一行扔出去会击倒多少僵尸就可以了。
复杂度 。
到这都还是蓝题水平,但开始扣代码就知道这题有多 Hard 了。
#include<bits/stdc++.h> #define ll long long #define L(x) t[x].l #define R(x) t[x].r #define mid (l+r>>1) #define lc x<<1,l,mid #define rc x<<1|1,mid+1,r #define OK Ll<=l&&r<=Rr #define Root 1,1,n #define rep(x,y,z) for(int x=(y);x<=(z);x++) #define per(x,y,z) for(int x=(y);x>=(z);x--) #define repn(x) rep(x,1,n) #define repm(x) rep(x,1,m) #define pb push_back #define e(x) for(int i=h[x],y=to[i];i;i=nxt[i],y=to[i]) #define E(x) for(auto y:p[x]) #define Pi pair<int,int> #define ui unsigned ll inline int read(){int s=0,w=1;char c=getchar();while(c<48||c>57) {if(c=='-') w=-1;c=getchar();}while(c>=48&&c<=57)s=(s<<1)+(s<<3)+c-48,c=getchar();return s*w;} inline void pf(int x){if(x<0) putchar('-'),x=-x;if(x>9)pf(x/10);putchar(x%10+48);} using namespace std; const int N =2e5+5,M=1e6+5,MM=N*2,inf=(1LL<<30)-1; mt19937 rd(20080626); int n,m,k,tot; bool Tiao=1; inline int idl(int x){ return x; } inline int idr(int x){ return x+tot; } struct node{ int x,y,id,ty; }a[N<<1]; map<Pi,int>P; int nxt[N<<1],pre[N<<1],Mx,root[N<<1]; struct seg{ int mx,id; }xd[N]; inline void getup(int x){ xd[x]=xd[x<<1].mx>=xd[x<<1|1].mx?xd[x<<1]:xd[x<<1|1]; } inline void modify(int x,int l,int r,int p,int k){ if(l==r)return xd[x]={k,l},void(); p<=mid?modify(lc,p,k):modify(rc,p,k),getup(x); } struct fhq{ int l,r,key,siz,sm,p,k,mp,f,le,lp; }t[MM]; int cnt; inline void create(int id,int ty,int ex){ a[id].ty>0?t[id+ty*tot]={0,0,(int)rd(),1,1,1,1,1,0,ex,ex}:t[id+ty*tot]={0,0,(int)rd(),1,0,inf,0,inf,0,ex,ex}; } inline void Getup(int x){ t[L(x)].f=t[R(x)].f=x; t[x].siz=t[L(x)].siz+t[R(x)].siz+1,t[x].sm=t[L(x)].sm+t[R(x)].sm+t[x].k; t[x].mp=min({t[L(x)].mp,t[L(x)].siz+t[x].p,t[L(x)].siz+1+t[R(x)].mp}); t[x].le=min({t[L(x)].le,t[L(x)].siz+t[x].lp,t[L(x)].siz+1+t[R(x)].le}); } inline Pi split(int x,int k){ if(!x)return {0,0}; t[x].f=0; if(k<=t[L(x)].siz){ Pi now=split(L(x),k); L(x)=now.second,Getup(x),t[now.first].f=0; return {now.first,x}; } Pi now=split(R(x),k-t[L(x)].siz-1); R(x)=now.first,Getup(x),t[now.second].f=0; return {x,now.second}; } inline int merge(int x,int y){ t[x].f=t[y].f=0; if(!x||!y)return x|y; if(t[x].key<t[y].key)return L(y)=merge(x,L(y)),Getup(y),y; return R(x)=merge(R(x),y),Getup(x),x; } inline int getrt(int x){ int nw=x; while(t[nw].f)nw=t[nw].f; return nw; } inline int getps(int x){ int ans=1+t[L(x)].siz; while(t[x].f){ if(x==R(t[x].f))ans+=t[L(t[x].f)].siz+1; x=t[x].f; } return ans; } int st[MM],tp; map<int,int>Q[20005]; bool v[MM]; inline int getid(int x){ return !Q[x].size()?0:(*Q[x].begin()).second; } inline void build(int s){ tp=0; while(s)st[++tp]=s,s=nxt[s]; int rt=st[1],k=0,id=0; rep(i,2,tp)rt=merge(rt,st[i]); rep(i,1,tp)if(v[st[i]])return modify(Root,a[st[i]].y,tp-i+1),void(); } inline int getr(int x){ while(R(x))x=R(x); return x; } inline int getl(int x){ while(L(x))x=L(x); return x; } inline int got(int rt){ if(!rt)return rt; int fir=t[rt].mp; if(fir>t[rt].siz)return rt; Pi now=split(rt,fir); st[++tp]=getr(now.first); if(st[tp]>tot)st[tp]-=tot; return merge(now.first,got(now.second)); } inline void del(int rt){ if(!rt)return; int x=t[rt].le; if(x>t[rt].siz)return; Pi now=split(rt,x); modify(Root,a[getr(now.first)].y,0),merge(now.first,now.second); } inline void ins(int rt){ if(!rt)return; int x=t[rt].le; if(x>t[rt].siz)return; Pi now=split(rt,x-1); int y=getl(now.second); if(y>tot)y-=tot; modify(Root,a[y].y,t[now.second].sm),merge(now.first,now.second); } inline void Clear(int x,int rt){ int ps=getps(x); Pi A=split(rt,ps-1),B=split(A.second,1); t[x].k=t[x].sm=0,t[x].le=t[x].lp=t[x].mp=t[x].p=inf; merge(A.first,merge(B.first,B.second)); } inline void Update(int x){ if(!x)return; int rt=getrt(x),ps=getps(x); del(rt); Pi A=split(rt,ps-1),B=split(A.second,1); t[x].k=t[x].sm=t[x].le=t[x].lp=t[x].mp=t[x].p=1,merge(A.first,merge(B.first,B.second)); } inline void Delete(int x){ int pid=getid(a[x].y),nid; v[x]=v[x+tot]=0,Q[a[x].y].erase(a[x].x),nid=getid(a[x].y); if(a[x].y<=n/2&&nid)nid+=tot; int rtl=getrt(x),rtr=getrt(x+tot); del(rtl),del(rtr),Clear(x,rtl),Clear(x+tot,rtr); if(pid==x)Update(nid); if(a[x].y!=1&&a[x].y!=n){ int psl=getps(x),psr=getps(x+tot); Pi A=split(rtl,psl-1),B=split(rtr,psr-1); rtl=merge(A.first,B.second),rtr=merge(B.first,A.second); } ins(rtl),ins(rtr); if(pid==x){ if(nid)ins(getrt(nid)); } } inline void solve(int s){ if(a[s].y<=n/2)s+=tot; tp=0; int rt=getrt(s),ps=getps(s); Pi now=split(rt,ps-1); now.second=got(now.second),rt=merge(now.first,now.second); rep(i,1,tp){ int x=st[i]; a[x].ty--; if(!a[x].ty)Delete(x); } } vector<int>p[N]; inline bool cmp(int x,int y){ if(x>tot)x-=tot;if(y>tot)y-=tot; return a[x].x<a[y].x; } signed main(){ n=read(),m=read(),k=read(),t[0].p=t[0].mp=t[0].le=t[0].lp=inf; repm(i){ int x=read(),y=read(); P[{x,y}]++,Mx=max(Mx,x); } repm(i)modify(Root,i,0); for(auto y:P)tot++,a[tot]={y.first.first,y.first.second,tot,y.second},Q[a[tot].y][a[tot].x]=tot; repn(i){ int id=getid(i); if(!id)continue; if(i<=n/2)v[idr(id)]=1; else v[idl(id)]=1; } rep(i,1,tot){ if(a[i].y!=1)p[(a[i].x+a[i].y-1)%(n*2-2)].pb(i); if(a[i].y!=n)p[((a[i].x-a[i].y+1)%(n*2-2)+n*2-2)%(n*2-2)].pb(i+tot); } rep(i,1,tot)a[i+tot]=a[i]; rep(i,0,n*2-3){ sort(p[i].begin(),p[i].end(),cmp); int siz=p[i].size(); rep(j,0,siz-2){ int y=p[i][j+1]; if(a[p[i][j+1]].y!=1&&a[p[i][j+1]].y!=n)y+=y<=tot?tot:-tot; nxt[p[i][j]]=y,pre[y]=p[i][j]; } } rep(i,1,tot)create(i,0,v[i]?1:inf),create(i,1,v[i+tot]?1:inf); rep(i,1,tot*2)if(!pre[i])build(i); int sum=0; while(k--){ printf("%d %d\n",xd[1].id,xd[1].mx); sum+=xd[1].mx; if(xd[1].mx>=1)solve(getid(xd[1].id)); } cout<<sum; return 0; }
- 1
信息
- ID
- 2347
- 时间
- 1000ms
- 内存
- 125MiB
- 难度
- 7
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者