[bzoj3353]Archery
tips1:下标相关均默认在的环上
tips2:可能需要大量的感性理解(后面我也已经神智不清了)
设排名为,将的编号为,的编号为
记为位置上两人的编号和,则每次从移动到的人编号为
在此基础上,不断找到二元组满足以下两种情况之一:
-
且
-
且(若不存在即所有人编号均为)
此时,经过轮比赛会使得,且不影响其余位置,不妨在初始处理
当不存在时,均同号(包含)且,进而每轮比赛即旋转或不变
关于如何找,维护两个栈和,并逆序遍历:
- 若,则在中加入个
- 若,则在中弹出个元素(与配对),不足则在中加入等量个
最终,不断将的栈顶和的栈底配对,并特判的情况
回到原问题,枚举所在位置,对是否分别求出最终的序列
两者恰有一个位置不同,且该位置即为的最终位置,时间复杂度为
特判,显然最终答案为(此时将后会使得所有人编号均为)
最终和取决于,化简得
在此基础上,仅需求出"不存在时"两者不同的位置,最终位置即该位置或不变
对于第一类中的,若,则将后仍满足其性质
将遍历顺序改为,则过程中选择的均满足
在此基础上,两者不同的位置有以下三种情况:
-
若,则
当后,会与栈顶底匹配,其余元素顺次向后匹配
最终,不同的位置即栈底的第个元素(额外匹配)
-
若且为空,则仅需考虑的情况
若,则不同的位置即,否则即
注意到后者与无关(即),可以直接预处理
-
若且不为空,类似第一种,不同的位置即栈顶第个元素(取消匹配)
另外,这总不会影响时的,这可以分类讨论:
- 若,即两次均选该位置
- 若,由于且最终非空,必然已经匹配
#include<bits/stdc++.h>
using namespace std;
const int N=400005;
int n,m,R,pos,ans,a[N];
vector<int>v,V;//st+和st-
int query(int k){
v.clear(),V.clear();
for(int i=k;i;i--){
if (a[(i<<1)-1])v.push_back(i);
if ((i<k)&&(a[i<<1]))v.push_back(i);
if (i>1){
if (v.empty())V.push_back(i);
else v.pop_back();
}
}
for(int i=n;i>k;i--){
if (a[(i<<1)-1])v.push_back(i);
if (a[(i<<1)-2])v.push_back(i);
if (v.empty())V.push_back(i);
else v.pop_back();
}
if (m>n+1)return V[v.size()];
if (!V.empty())k=v[v.size()-V.size()];
else{
for(int i=1;i<(n<<1);i++)
if (!a[i]){
if (i>=(k<<1))k=(i>>1)+1;
break;
}
}
return (k-R%n+n-1)%n+1;
}
int main(){
scanf("%d%d%d",&n,&R,&m);
if (m==1){
printf("%d\n",n);
return 0;
}
for(int i=1;i<(n<<1);i++){
scanf("%d",&a[i]);
a[i]=(a[i]<m ? 0 : 1);
}
ans=n+1;
for(int i=n;i;i--){
int s=query(i);
if (s<ans)pos=i,ans=s;
}
printf("%d\n",pos);
return 0;
}
考虑分别处理出逆序遍历和后的结果,即可实现query,即
if (svp[k]<sVs[k+1]){
if (m>n+1){
if (svs[k+1]<sVp[k])return Vp[k][sVp[k]-svs[k+1]-1];
return Vs[k+1][svs[k+1]-sVp[k]+svp[k]];
}
return (vs[k+1][svs[k+1]-(sVp[k]+sVs[k+1]-svp[k])]-R%n+n-1)%n+1;
}
else{
if (m>n+1)return Vp[k][sVp[k]-(svp[k]-sVs[k+1]+svs[k+1])-1];
if (sVp[k]){
int s=svp[k]-sVs[k+1]+svs[k+1]-sVp[k];
if (s<svp[k]-sVs[k+1])k=vp[k][svp[k]-s-1];
else k=vs[k+1][s-(svp[k]-sVs[k+1])];
}
else{
if ((k<<1)<=mn)k=(mn>>1)+1;
}
return (k-R%n+n-1)%n+1;
}
(其中表示的翻转后,表示的,表示的大小)
关于,分类讨论后,即
for(int i=2;i<=n;i++){
vp[i]=vp[i-1],Vp[i]=Vp[i-1];
if (a[(i<<1)-2]){
if (Vp[i].empty())vp[i].push_back(i-1);
else Vp[i].pop_back();
}
if (!a[(i<<1)-1])Vp[i].push_back(i);
}
关于,分类讨论后,即
for(int i=n;i;i--){
vs[i]=vs[i+1],Vs[i]=Vs[i+1];
if (a[(i<<1)-1])vs[i].push_back(i);
if (a[(i<<1)-2])vs[i].push_back(i);
if (vs[i].empty())Vs[i].push_back(i);
else vs[i].pop_back();
}
逆序(指)做一遍,存储每次vs[i].pop_back()的数后即可撤销
由于复杂度瓶颈在于拷贝,此时即可在线做,时间复杂度为
#include<bits/stdc++.h>
using namespace std;
const int N=400005;
int n,m,R,mn,svp,sVp,svs,sVs,pos,ans,a[N],z[N];
vector<int>vp,Vp,vs,Vs;
int query(int k){
if (svp<sVs){
if (m>n+1){
if (svs<sVp)return Vp[sVp-svs-1];
return Vs[svs-sVp+svp];
}
return (vs[svs-(sVp+sVs-svp)]-R%n+n-1)%n+1;
}
else{
if (m>n+1)return Vp[sVp-(svp-sVs+svs)-1];
if (sVp){
int s=svp-sVs+svs-sVp;
if (s<svp-sVs)k=vp[svp-s-1];
else k=vs[s-(svp-sVs)];
}
else{
if ((k<<1)<=mn)k=(mn>>1)+1;
}
return (k-R%n+n-1)%n+1;
}
return 0;
}
int main(){
scanf("%d%d%d",&n,&R,&m);
if (m==1){
printf("%d\n",n);
return 0;
}
for(int i=1;i<(n<<1);i++){
scanf("%d",&a[i]);
a[i]=(a[i]<m ? 0 : 1);
}
for(int i=1;i<(n<<1);i++)
if (!a[i]){mn=i;break;}
for(int i=n;i;i--){
if (a[(i<<1)-1])svs++,vs.push_back(i);
if (a[(i<<1)-2])svs++,vs.push_back(i);
z[i]=(svs ? vs.back() : 0);
if (!svs)sVs++,Vs.push_back(i);
else svs--,vs.pop_back();
}
ans=n+1;
for(int i=1;i<=n;i++){
if (i==1){
if (a[1])svp++,vp.push_back(1);
}
else{
if (a[(i<<1)-2]){
if (!sVp)svp++,vp.push_back(i-1);
else sVp--,Vp.pop_back();
}
if (!a[(i<<1)-1])sVp++,Vp.push_back(i);
}
if (z[i])svs++,vs.push_back(z[i]);
else sVs--,Vs.pop_back();
if (a[(i<<1)-1])svs--,vs.pop_back();
if (a[(i<<1)-2])svs--,vs.pop_back();
int s=query(i);
if (s<=ans)pos=i,ans=s;
}
printf("%d\n",pos);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
2022-03-02 [uoj671]诡异操作
2021-03-02 [cf1491G]Switch and Flip
2021-03-02 [cf1491F]Magnets