「NOI2017」整数

有一些比较简单的\(\log^2n\)做法

比如暴力在动态开点线段树上维护每个位置为\(0\)还是\(1\),我们发现涉及到某一位加上\(1\)或者减去\(1\)实际上对其他位的影响只有区间覆盖,通过线段树上二分可以得到区间覆盖的位置,然后暴力区间覆盖即可。

反正我这种菜鸡大常数写法只得到了68分..


考虑利用势能,注意到如果同时改变加法和减法,势能很容易被\(b\)搞掉

如果分开维护加法和减法,把位置上的\(1\)的个数当做势能,可以发现,暴力修改是均摊\(O(n\log a)\)的

直接暴力维护两个数组\(plu\)和\(dec\)

考虑单点求值,因为保证了\(x\ge 0\)

所以我们发现只需要两个条件就可以确定第\(k\)位的值,即

  • \(ans_1=[plu_k=dec_k]\)
  • \(ans_2=[plu[k-1,1]\ge[dec[k-1,1]]]\),这里是倒着进行字符串比较的意思

第\(k\)位的答案即为\(ans_1 \ xor \ ans_2\),这里讨论一下就可以得到了

考虑找到\(\le p\)位置的两个数组第一个不同的位置,然后比较大小

一个暴力的想法是,把每个不同的位置塞到set里面去,然后每次在set里面二分找一下位置,也是\(\log^2n\)的

考虑到每次修改的一个长为\(\log a\)连续的区间(这里实际上饶了一个大圈子)

所以把区间每\(\log a\)分一块,块也是有势能的,然后set里面一次赛一个块就可以了

复杂度就一个\(\log\)了


Code:

#include <cstdio>
#include <cctype>
#include <set>
#include <algorithm>
#define ll long long
using std::min;
const int SIZE=1<<21;
char ibuf[SIZE],*iS,*iT;
//#define gc() (iS==iT?(iT=(iS=ibuf)+fread(ibuf,1,SIZE,stdin),iS==iT?EOF:*iS++):*iS++)
#define gc() getchar()
template <class T>
void read(T &x)
{
int f=0;x=0;char c=gc();
while(!isdigit(c)) f|=c=='-',c=gc();
while(isdigit(c)) x=x*10+c-'0',c=gc();
if(f) x=-x;
}
const int N=1e6+10;
int n,t1,t2,t3;
int plu[N*30],dec[N*30],bel[N*30];
int edt[N],vis[N];
std::set <int> s;
std::set <int>::iterator it;
int qry(int p)
{
while(p%32!=0&&plu[p]==dec[p]) --p;
if(plu[p]!=dec[p])
{
if(plu[p]>dec[p]) return 1;
else return 0;
}
p=bel[p];
it=s.upper_bound(p);
if(s.empty()||it==s.begin()) return 1;
--it;
p=(*it)*32;
while(plu[p]==dec[p]) --p;
if(plu[p]>dec[p]) return 1;
else return 0;
}
int main()
{
read(n),read(t1),read(t2),read(t3);
int m=n*30+31,T=(m-1)/32+1;
for(int L,R=0,i=1;i<=T;i++)
{
L=R+1,R=i*32;
for(int j=L;j<=R;j++) bel[j]=i;
}
for(int op,a,b,k,i=1;i<=n;i++)
{
read(op);
if(op==1)
{
edt[0]=0;
read(a),read(b);
if(a>0)
{
for(int p,j=1;j<=30;j++)
if(a>>j-1&1)
{
p=j+b;
if(vis[bel[p]]!=i)
edt[++edt[0]]=bel[p],vis[bel[p]]=i;
while(plu[p])
{
plu[p++]=0;
if(vis[bel[p]]!=i)
edt[++edt[0]]=bel[p],vis[bel[p]]=i;
}
plu[p]=1;
}
}
else
{
a=-a;
for(int p,j=1;j<=30;j++)
if(a>>j-1&1)
{
p=j+b;
if(vis[bel[p]]!=i)
edt[++edt[0]]=bel[p],vis[bel[p]]=i;
while(dec[p])
{
dec[p++]=0;
if(vis[dec[p]]!=i)
edt[++edt[0]]=bel[p],vis[bel[p]]=i;
}
dec[p]=1;
}
}
for(int j=1;j<=edt[0];j++)
{
int L=(edt[j]-1)*32+1,R=edt[j]*32,flag=1;
for(int l=L;l<=R;l++)
if(plu[l]!=dec[l])
{
flag=0;
break;
}
if(flag)
{
if(s.find(edt[j])!=s.end()) s.erase(edt[j]);
}
else
s.insert(edt[j]);
}
}
else
{
read(k);
int p=k++;
int ans=0;
if(plu[k]==dec[k]) ans=1;
printf("%d\n",ans^qry(p));
}
}
return 0;
}

2019.5.31

「NOI2017」整数 解题报告的更多相关文章

  1. 「NOI2017」蔬菜 解题报告

    「NOI2017」蔬菜 首先考虑流 可以从 \(s\) 流入表示得到蔬菜,流出到 \(t\) 表示卖出蔬菜,给每个蔬菜拆点,并给它它每天应得的蔬菜. 但是我们没办法直接给,注意到如果把变质看成得到并可 ...

  2. 「NOI2017」游戏 解题报告

    「NOI2017」游戏 \(d\)这么小,你考虑直接对\(d\)个东西暴力 枚举\(x\)为\(a\)或\(b\)(\(c\)就不用了,因为\(a,b\)已经包含\(c\))了,剩下的就是个\(2-s ...

  3. LibreOJ2302 - 「NOI2017」整数

    Portal Description 有一个整数\(x=0\),对其进行\(n(n\leq10^6)\)次操作: 给出\(a(|a|\leq10^9),b(b\leq30n)\),将\(x\)加上\( ...

  4. 「ZJOI2016」旅行者 解题报告

    「ZJOI2016」旅行者 对网格图进行分治. 每次从中间选一列,然后枚举每个这一列的格子作为起点跑最短路,进入子矩形时把询问划分一下,有点类似整体二分 至于复杂度么,我不会阿 Code: #incl ...

  5. 「HNOI2016」树 解题报告

    「HNOI2016」树 事毒瘤题... 我一开始以为每次把大树的子树再接给大树,然后死活不知道咋做,心想怕不是个神仙题哦 然后看题解后才发现是把模板树的子树给大树,虽然思维上难度没啥了,但是还是很难写 ...

  6. 「HNOI2016」序列 解题报告

    「HNOI2016」序列 有一些高妙的做法,懒得看 考虑莫队,考虑莫队咋移动区间 然后你在区间内部找一个最小值的位置,假设现在从右边加 最小值左边区间显然可以\(O(1)\),最小值右边的区间是断掉的 ...

  7. 「HNOI2016」网络 解题报告

    「HNOI2016」网络 我有一个绝妙的可持久化树套树思路,可惜的是,它的空间是\(n\log^2 n\)的... 注意到对一个询问,我们可以二分答案 然后统计经过这个点大于当前答案的路径条数,如果这 ...

  8. 「HAOI2018」染色 解题报告

    「HAOI2018」染色 是个套路题.. 考虑容斥 则恰好为\(k\)个颜色恰好为\(c\)次的贡献为 \[ \binom{m}{k}\sum_{i\ge k}(-1)^{i-k}\binom{m-k ...

  9. 「HNOI2016」最小公倍数 解题报告

    「HNOI2016」最小公倍数 考虑暴力,对每个询问,处理出\(\le a,\le b\)的与询问点在一起的联通块,然后判断是否是一个联通块,且联通块\(a,b\)最大值是否满足要求. 然后很显然需要 ...

随机推荐

  1. 接口参数校验之@Valid与BindingResult

    接口方法往往需要对入参做一些校验,从而判断入参是否合格,而javax.validation包为我们提供了一些常用的参数校验注解,使用起来很方便. 下面这个示例是检验入参对象中的password是否为空 ...

  2. mybatis模糊查询(转载)

    原文地址:http://blog.csdn.net/luqin1988/article/details/7865643 模糊查询: 1. sql中字符串拼接 SELECT * FROM tableNa ...

  3. BZOJ 2761: [JLOI2011]不重复数字 set

    Description 给出N个数,要求把其中重复的去掉,只保留第一次出现的数. 例如,给出的数为1 2 18 3 3 19 2 3 6 5 4,其中2和3有重复,去除后的结果为1 2 18 3 19 ...

  4. webpack对脚本和样式的处理

    一.对js处理 webpack本身支持js加载也可以用插件. 1.加载要全局使用的插件比如jquery 在页面用cdn方式引用,然后再webpack.config.js里配置.会让jquery成为全局 ...

  5. jQuery积累:serialize()、stringify()、toJSON()

    *)表单serialize()序列化,和serializeArray() ##)应用场景 当Ajax或者get请求发送表单中的某一个,或者某几个值到后台时,通过jQuery就能获取到这些值.然后作为A ...

  6. python global和nonlocal的使用

    ◆global和nonlocal是Python的两个重要变量作用域关键字 1.global用在全局变量,应用场景: 变量定义在函数外部的时候,如果函数里面想改变这个全局变量的值,需要在当前的引用函数里 ...

  7. yii2和laravel比较

    yii2和laravel比较 一.总结 一句话总结: 开发速度两者相当:laravel的artisan工具和yii的gii有异曲同工的效果,借助于artisan工具,可以快速创建控制器.模型和路由等. ...

  8. 建站手册-网站建设:Web 安全

    ylbtech-建站手册-网站建设:Web 安全 1.返回顶部 1. http://www.w3school.com.cn/site/site_security.asp 2. 2.返回顶部 1. 此刻 ...

  9. HBase 中加盐之后的表如何读取:Spark 篇

    在 <HBase 中加盐之后的表如何读取:协处理器篇> 文章中介绍了使用协处理器来查询加盐之后的表,本文将介绍第二种方法来实现相同的功能. 我们知道,HBase 为我们提供了 hbase- ...

  10. 迪杰斯特拉算法(Dijkstra)

    模板一: 时间复杂度O(n2) int dijkstra(int s,int m) //s为起点,m为终点 { memset(dist,,sizeof(dist)); //初始化,dist数组用来储存 ...