[XJOI]noip44 T3还有这种操作
还有这种操作
ttt 最近在学习二进制, 他想知道小于等于N的数中有多少个数的二进制表示中有偶数个1。
但是他想了想觉得不够dark,于是他增加了若干次操作,每次操作会将一个区间内的0变1 , 1变0,
现在在每次操作之后,他都想知道原来的那个问题的答案。
输入格式:
第一行:一个01序列表示N的二进制表示
第二行:操作次数 m
接下来的m行每行两个数,表示要操作的区间。
输出格式:
输出m+1行,第一行表示初始的答案,第二行到第m+1行输出每次操作后的答案
答案对1e9 + 7 取模
样例输入:
0
1
1 1
样例输出:
1
1
数据范围:
设 n为 N 的 位数
- 10%, n <= 20, m <= 100
- 30%, n <= 60, m <= 10000
- 60%, n <= 1000, m <= 10000
- 100%, n <= 1000000, m <= 100000
解题思路:
在看到n<=2^1000000时,我的内心是震惊的,想着或者是字典树,线段树
于是想着线段树方向想,但是怎么统计答案又成为了一个问题...
加之题目并没有说l<=r,于是这道题就愉快的爆零了
***下面是正题
我们想用一个线段树,维护每一位的翻转次数,以及每一位的答案的值
那么我们就可以用nlogn的时间建出它,并用mlogn的时间来查询。
好线段树部分讲完了
***下面是关于统计答案的
我们首先可以发现
[0,1)内有2^0=1个
[0,10)内有2^0=1个
[0,100)内有2^1=2个
[0,1000)内有2^2=4个(以上数均为二进制表示)
...
那么我们可以总结了,[0,100..00(n个0))内有2^(n-1)个数满足,此时n>=1(为什么下面会讲)
但是知道这个有什么用么?
我们想一个 1010=1000+10
答案就为[0,1000)+[0,10)+check(1010是否满足)
这个结论的证明留给读者去完成
***于是这个程序基本就成型了
注意:(1)l是可能大于r的
(2)在对于最后一位处理,需要特殊处理,否则,对于最后一位是1的数,会出现1的差别,
例如:101 如按原先方法计算,答案为2+1+check(101)=4,而正确答案是3
因此在遇到原串符合条件,且最后一位是1时,要对答案减一
#include<bits/stdc++.h>
using namespace std;
const int N=5e6+,p=1e9+;
struct xint {int l,r;}a[N];
int val[N],sum[N],pw[N],bo[N],n[N],m,l,r;
char s[N]; bool flag;
void pushup(int rt,int len){
val[rt]=(1ll*val[rt<<]*pw[len]+val[rt<<|])%p;
sum[rt]=sum[rt<<]^sum[rt<<|];
}
void opera(int rt){
bo[rt]^=; val[rt]=((pw[a[rt].r-a[rt].l+]--val[rt])%p+p)%p;
sum[rt]=((a[rt].r-a[rt].l+)&)^sum[rt];
}
void pushdown(int rt){
if (bo[rt]) opera(rt*),opera(rt*+),bo[rt]=;
}
//--------------------------------
void build(int l,int r,int rt){
if (l>r) return; a[rt].l=l; a[rt].r=r;
if (l==r){
val[rt]=sum[rt]=n[l]; return;
}
int mid=(l+r)>>;
build(l,mid,rt<<); build(mid+,r,rt<<|);
pushup(rt,r-mid);
} void update(int l,int r,int rt){
if (l>r) return;
if (a[rt].l==l&&a[rt].r==r){
opera(rt); return;
}
int mid=(a[rt].l+a[rt].r)>>; pushdown(rt);
if(r<=mid) update(l,r,rt<<);
else if (l>mid) update(l,r,rt<<|);
else update(l,mid,rt<<),update(mid+,r,rt<<|);
pushup(rt,a[rt].r-mid);
}
int query(){
return (val[]+bool(!sum[]||flag))%p;
}
//------------------------------
int main(){
scanf("%s%d",s+,&m); int len=strlen(s+);
for (int i=len;i>=;--i) n[i]=s[i]-''; pw[]=;
for (int i=;i<=len;++i) pw[i]=pw[i-]*%p;
build(,len-,); flag=n[len]; printf("%d\n",query());
while (m--){
scanf("%d%d",&l,&r);
if (l>r) swap(l,r);
if (r==len) r--,flag^=;
update(l,r,); printf("%d\n",query());
}
}
总结:个人觉得这是一道很好的线段树题目,当然对于我这种蒟蒻,线段树还不能熟练掌握的还要加油
***虽说联赛不考
[XJOI]noip44 T3还有这种操作的更多相关文章
- 【翻译】MongoDB指南/CRUD操作(三)
[原文地址]https://docs.mongodb.com/manual/ CRUD操作(三) 主要内容: 原子性和事务(Atomicity and Transactions),读隔离.一致性和新近 ...
- Oracle补全日志(Supplemental logging)
Oracle补全日志(Supplemental logging)特性因其作用的不同可分为以下几种:最小(Minimal),支持所有字段(all),支持主键(primary key),支持唯一键(uni ...
- std::thread使用
本文将从以下三个部分介绍C++11标准中的thread类,本文主要内容为: 启动新线程 等待线程与分离线程 线程唯一标识符 1.启动线程 线程再std::threada对象创建时启动.最简单的情况下, ...
- MySQL在并发场景下的问题及解决思路
目录 1.背景 2.表锁导致的慢查询的问题 3.线上修改表结构有哪些风险? 4.一个死锁问题的分析 5.锁等待问题的分析 6.小结 1.背景 对于数据库系统来说在多用户并发条件下提高并发性的同时又要保 ...
- [日常] NOIP前集训日记
写点流水账放松身心... 10.8 前一天考完NHEEE的一调考试终于可以开始集训了Orz (然后上来考试就迟到5min, GG) T1维护队列瞎贪心, 过了大样例交上去一点也不稳...T出翔只拿了5 ...
- CountDownLatch、CyclicBarrier和Semaphore 使用示例及原理
备注:博客园的markDown格式支持的特别不友好.也欢迎查看我的csdn的此篇文章链接:CountDownLatch.CyclicBarrier和Semaphore 使用示例及原理 CountDow ...
- DB2 rollforward 命令使用详解
DB2 rollforward 命令使用详解 原文:https://www.ibm.com/developerworks/cn/data/library/techarticles/dm-1003wuc ...
- 【黑金原创教程】【FPGA那些事儿-驱动篇I 】实验十四:储存模块
实验十四比起动手笔者更加注重原理,因为实验十四要讨论的东西,不是其它而是低级建模II之一的模块类,即储存模块.接触顺序语言之际,“储存”不禁让人联想到变量或者数组,结果它们好比数据的暂存空间. . i ...
- Oracle Supplemental 补全日志介绍
转. Oracle补全日志(Supplemental logging)特性因其作用的不同可分为以下几种:最小(Minimal),支持所有字段(all),支持主键(primary key),支持唯一键( ...
随机推荐
- (转) Arcgis for js加载百度地图
http://blog.csdn.net/gisshixisheng/article/details/44853709 概述: 在前面的文章里提到了Arcgis for js加载天地图,在本节,继续讲 ...
- html formData 数据 提交和 .netMVC接收
<form id="uploadForm" enctype="multipart/form-data"> <input type=" ...
- python 疑难杂症
1.getpass模块 :Pycharm不支持getpass模块,使用terminal可运行,但是getpass中文提示显示乱码?
- swift-导航栏添加自定义返回按钮
//1.添加返回按钮 func addBackBtn(){ let leftBtn:UIBarButtonItem=UIBarButtonItem(title: "返回", sty ...
- PL\SQL(day05)
PLSQL 1.常用的访问数据库的相关技术 1) plsql 过程化的sql 2) proc/c++ 在c/c++语言中访问oracle数据库的技术 3) ado/odbc vc中访问数据库的技术 4 ...
- request.getScheme()、 request.getServerName() 、 request.getServerPort() 、 request.getContextPath()
<% String basePath = request.getScheme() + "://" + request.getServerName() + ":&qu ...
- 50.常用的query查询方式
主要知识点 match all match multi match range query term query terms query exist query 1.match all ...
- 1.3 eclipse中配置Tomcat
下载并成功安装Eclipse和Tomcat(): 打开Eclipse,单击“window”菜单,选择下方的“Preferences”: 步骤阅读 3 找到Server下方的Runtime Envi ...
- Bootstrap 表单控件一(单行输入框input,下拉选择框select ,文本域textarea)
单行输入框,常见的文本输入框,也就是input的type属性值为text.在Bootstrap中使用input时也必须添加type类型,如果没有指定type类型,将无法得到正确的样式,因为Bootst ...
- 数位dp无前导零
题目链接:http:// www.lydsy.com/JudgeOnline/problem.php?id=1026 #include <iostream> #include < ...