「SCOI2015」小凸解密码

题意:给一个环,定义一段连续的极长\(0\)串为\(0\)区间,定义一个位置的离一个\(0\)区间的距离为这个位置离这个区间中\(0\)的距离的最小值,每次询问一个位置,求离它最远的\(0\)区间与它的距离,带修改


于是我是多sb才会想到在点分裂平衡树上做类似三分的sb操作?

而且我现在的代码还是错的,只有srand的fhq才能过,不过根据对拍,错误概率很小。

思路,在平衡树上维护\(0\)区间的相对位置

然后每个点维护子树最左区间和子树最右区间

我们把每个询问的时候的那个位置劈开

就变成了两个单峰的上凸的东西

在平衡树上移动就可以了

我似乎还是挂在了相同元素上?

因为写了太久,所以懒得想为啥错了


Code:

#include <cstdio>
#include <cctype>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <algorithm>
using std::min;
using std::max;
const int N=2e5+10;
template <class T>
void read(T &x)
{
x=0;char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)) x=x*10+c-'0',c=getchar();
}
int n,m,a[N],b[N];
char c[N][5];
int ch[N][2],L[N],R[N],lL[N],lR[N],rL[N],rR[N],val[N],tot,root;
#define ls ch[now][0]
#define rs ch[now][1]
int New(int l,int r)
{
val[++tot]=rand(),lL[tot]=rL[tot]=L[tot]=l,lR[tot]=rR[tot]=R[tot]=r;
return tot;
}
void updata(int now)
{
lL[now]=rL[now]=L[now];
lR[now]=rR[now]=R[now];
if(ls) lL[now]=lL[ls],lR[now]=lR[ls];
if(rs) rL[now]=rL[rs],rR[now]=rR[rs];
}
void split(int now,int &x,int &y,int k)
{
if(!now){x=y=0;return;}
if(L[now]<=k) x=now,split(rs,rs,y,k);
else y=now,split(ls,x,ls,k);
updata(now);
}
int Merge(int x,int y)
{
if(!x||!y) return x^y;
if(val[x]<val[y])
{
ch[x][1]=Merge(ch[x][1],y);
updata(x);
return x;
}
else
{
ch[y][0]=Merge(x,ch[y][0]);
updata(y);
return y;
}
}
void Insert(int now)
{
int x,y;
split(root,x,y,L[now]);
root=Merge(x,Merge(now,y));
}
void build()
{
int las=-1;
for(int i=0;i<n;i++)
{
if(las==-1&&!b[i]) las=i;
if(~las&&b[i]) Insert(New(las,i-1)),las=-1;
}
if(~las) Insert(New(las,n-1));
}
int getl(int now)
{
if(ls) return getl(ls);
return now;
}
int getr(int now)
{
if(rs) return getr(rs);
return now;
}
void modi(int pos,int typ)
{
if(typ)
{
if(c[pos][0]=='+') b[pos]=(a[pos?pos-1:n-1]+a[pos])%10;
else b[pos]=a[pos?pos-1:n-1]*a[pos]%10;
}
int x,y,z;
if(b[pos])
{
split(root,x,y,pos);
int now=getr(x);
if(pos>R[now])
{
root=Merge(x,y);
return;
}
if(L[now]==R[now]) split(x,x,z,L[now]-1);
else
{
if(L[now]==pos) ++L[now],updata(now);
else if(R[now]==pos) --R[now],updata(now);
else
{
z=New(pos+1,R[now]);
R[now]=pos-1;
updata(now);
x=Merge(x,z);
}
}
root=Merge(x,y);
}
else
{
split(root,x,y,pos);
int nowl=getr(x),nowr=getl(y);
if(L[nowl]<=pos&&pos<=R[nowl]){root=Merge(x,y);return;}
if(R[nowl]+1==pos) ++R[nowl],updata(nowl);
else if(L[nowr]-1==pos) --L[nowr],updata(nowr);
else {root=Merge(x,Merge(New(pos,pos),y));return;}
if(R[nowl]==L[nowr]-1)
{
R[nowl]=R[nowr];
updata(nowl);
split(y,z,y,R[nowr]);
}
root=Merge(x,y);
}
}
void change()
{
int pos;
read(pos),read(a[pos]),scanf("%s",c[pos]);
modi(pos,1);
modi(pos==n-1?0:pos+1,1);
}
int dis(int l,int r,int p)
{
return l<=p&&p<=r?0:(p<l?min(l-p,p+n-r):min(p-r,l+n-p));
}
int ans,le,ri;
void query(int now,int p)
{
if(!now) return;
int dn=dis(L[now],R[now],p);
ans=max(ans,dn);
if(ls)
{
int dl=dis(rL[ls],rR[ls],p);
if(dn<=dl) query(ls,p);
}
if(rs)
{
int dr=dis(lL[rs],lR[rs],p);
if(dn<=dr) query(rs,p);
}
}
void qry()
{
int pos;ans=0;
read(pos);
b[pos]=a[pos];
modi(pos,0);
if(!root)
{
puts("-1");
modi(pos,1);
return;
}
le=getl(root),ri=getr(root);
if(le==ri)
{
printf("%d\n",dis(L[le],R[ri],pos));
modi(pos,1);
return;
}
if(L[le]==0&&R[ri]==n-1)
{
ans=min(dis(0,R[le],pos),dis(L[ri],n-1,pos));
split(root,le,root,0);
split(root,root,ri,L[ri]-1);
}
else le=ri=0;
int x,y;
split(root,x,y,pos);
query(x,pos),query(y,pos);
root=Merge(x,y);
root=Merge(le,Merge(root,ri));
modi(pos,1);
printf("%d\n",ans);
}
int main()
{
srand(time(0));
memset(L,0x3f,sizeof L);
memset(R,0x3f,sizeof R);
read(n),read(m);
for(int i=0;i<n;i++) read(a[i]),scanf("%s",c[i]);
for(int i=0;i<n;i++)
{
if(c[i][0]=='+') b[i]=(a[i?i-1:n-1]+a[i])%10;
else b[i]=a[i?i-1:n-1]*a[i]%10;
}
build();
for(int op,i=1;i<=m;i++)
{
read(op);
if(op==1) change();
else qry();
}
return 0;
}

2019.2.28

「SCOI2015」小凸解密码 解题报告的更多相关文章

  1. 「SCOI2015」小凸想跑步 解题报告

    「SCOI2015」小凸想跑步 最开始以为和多边形的重心有关,后来发现多边形的重心没啥好玩的性质 实际上你把面积小于的不等式列出来,发现是一次的,那么就可以半平面交了 Code: #include & ...

  2. 「SCOI2015」小凸玩矩阵 解题报告

    「SCOI2015」小凸玩矩阵 我好沙茶啊 把点当边连接行和列,在外面二分答案跑图的匹配就行了 我最开始二分方向搞反了,样例没过. 脑袋一抽,这绝壁要费用流,连忙打了个KM 然后wa了,一想这个不是完 ...

  3. 「SCOI2015」小凸玩密室 解题报告

    「SCOI2015」小凸玩密室 虽然有心里在想一些奇奇怪怪的事情的原因,不过还是写太久了.. 不过这个题本身也挺厉害的 注意第一个被点亮的是任意选的,我最开始压根没注意到 \(dp_{i,j}\)代表 ...

  4. 【LOJ】#2010. 「SCOI2015」小凸解密码

    题解 断环为链,把链复制两份 用set维护一下全是0的区间,然后查找x + n / 2附近的区间,附近各一个过不去,最后弃疗了改为查附近的两个,然后过掉了= = 熟练掌握stl的应用,你值得拥有(雾 ...

  5. loj#2009.「SCOI2015」小凸玩密室

    题目链接 loj#2009. 「SCOI2015」小凸玩密室 题解 树高不会很高<=20 点亮灯泡x,点亮x的一个子树,再点亮x另外的子树, 然后回到x的父节点,点亮父节点之后再点亮父节点的其他 ...

  6. LibreOJ #2006. 「SCOI2015」小凸玩矩阵 二分答案+二分匹配

    #2006. 「SCOI2015」小凸玩矩阵 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: 匿名 提交提交记录统计讨论测试数据   题目描述 ...

  7. AC日记——「SCOI2015」小凸玩矩阵 LiBreOJ 2006

    「SCOI2015」小凸玩矩阵 思路: 二分+最大流: 代码: #include <bits/stdc++.h> using namespace std; #define maxn 300 ...

  8. loj #2008. 「SCOI2015」小凸想跑步

    #2008. 「SCOI2015」小凸想跑步   题目描述 小凸晚上喜欢到操场跑步,今天他跑完两圈之后,他玩起了这样一个游戏. 操场是个凸 n nn 边形,N NN 个顶点按照逆时针从 0∼n−1 0 ...

  9. loj #2006. 「SCOI2015」小凸玩矩阵

    #2006. 「SCOI2015」小凸玩矩阵   题目描述 小凸和小方是好朋友,小方给小凸一个 N×M N \times MN×M(N≤M N \leq MN≤M)的矩阵 A AA,要求小凸从其中选出 ...

随机推荐

  1. 多线程系列之三:Immutable 模式

    一,什么是Immutable模式?immutable就是不变的,不发生改变的.Immutable模式中存在着确保实例状态不发生变化改变的类.这些实例不需要互斥处理.String就是一个Immutabl ...

  2. Windows Docker 安装

    win7.win8 .win10等需要利用 docker toolbox 来安装,国内可以使用阿里云的镜像来下载,下载地址:http://mirrors.aliyun.com/docker-toolb ...

  3. java lang(Comparable接口) 和java util(Comparator接口)分析比较

    //Comparable 接口强行对实现它的每个类的对象进行整体排序. -- 自然排序.类的compareTo称为自然比较方法. public interface Comparable<T> ...

  4. git简介及安装(win10)

    一句话介绍git Git是Linus Torvalds编写,目前是世界上最先进的分布式版本控制系统. git能干什么? 代码备份.还原,版本管理,分支管理,解决冲突,协同开发... 安装git > ...

  5. snv的使用

    1.搭建SVN服务器 (1)直接安装 (2)创建工号,分组,分配权限(图形化界面的直接操作,非图形界面的需要改配置文件conf文件夹下) (3)创建仓库,D:\Repositories\OA:cmd命 ...

  6. python数据结构与算法第十五天【二叉树】

    1.树的特点 (1)每个节点有零个或多个子节点: (2)没有父节点的节点称为根节点: (3)每一个非根节点有且只有一个父节点: (4)除了根节点外,每个子节点可以分为多个不相交的子树: 2.树的种类 ...

  7. extensions

    extensions.blocklist.enabled

  8. ASP.NET Core 2.0 Cookie Authentication

    using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Builder; using Microso ...

  9. tomcat9 点击bin目录下的startup.bat一闪而过

    我装的是tomcat9免安装版,jdk版本是11,之后去tomcat bin目录下点击startup.bat闪退(好吧,只有想办法解决了) 博客中的解决办法五花八门,什么环境变量没配好....不过都不 ...

  10. 简单介绍一下在CentOS上安装Docker。

    简单介绍一下在CentOS上安装Docker. 前置条件: 64-bit 系统 kernel 3.10+ 1.检查内核版本,返回的值大于3.10即可. $ uname -r 2.使用 sudo 或 r ...