【BZOJ4942】[Noi2017]整数

题目描述去uoj

题解:如果只有加法,那么直接暴力即可。。。(因为1的数量最多nlogn个)

先考虑加法,比较显然的做法就是将A二进制分解成log位,然后依次更新这log位,如果最高位依然有进位,那么找到最高位后面的第一个0,将中间的所有1变成0,那个0变成1。这个显然要用到线段树,但是复杂度是nlog2n的,肯定过不去。

于是我在考场上yy了一下,这log位是连续的,我们每次都要花费log的时间去修改一个岂不是很浪费?我们可以先在线段树上找到这段区间,然后在线段树上dfs下去,这样,时间复杂度就变成O(logn+那段区间在线段树上的大小)。因为一颗正常的线段树的大小就是4*n的,而这里的那段区间的大小是log的,所以我猜测复杂度应该是log*常数的。但是不会证,考完试旁边的大佬都十分怀疑我的复杂度,搞得我也非常怀疑,但是。。但是AC了。

正解貌似是O(nlog2n/32)的线段树+压位?听说考场上这么写的全被卡常了,体会到了wys的险恶用心~

回来重码了一发,交到uoj上TLE了,交到BZ上AC了(因为是均摊复杂度嘛~)。

欢迎大佬告诉我这个算法的真正复杂度~

#include <cstdio>
#include <cstring>
#include <iostream>
#define lson x<<1
#define rson x<<1|1
using namespace std;
const int N=30000040;
int n,A,B,nxt,f,len;
int s[N+1<<2],p[50];
void pushdown(int l,int r,int x)
{
if(!s[x]) s[lson]=s[rson]=0;
if(s[x]==r-l+1)
{
int mid=l+r>>1;
s[lson]=mid-l+1,s[rson]=r-mid;
}
}
void pushup(int x)
{
s[x]=s[lson]+s[rson];
}
void dfs(int l,int r,int x)
{
if(l==r)
{
s[x]+=p[l-B];
while(s[x]>1) p[l-B+1]++,s[x]-=2;
while(s[x]<0) p[l-B+1]--,s[x]+=2;
return ;
}
pushdown(l,r,x);
int mid=l+r>>1;
dfs(l,mid,lson),dfs(mid+1,r,rson);
pushup(x);
}
void updata(int l,int r,int x,int a,int b)
{
if(a<=l&&r<=b)
{
dfs(l,r,x);
return ;
}
pushdown(l,r,x);
int mid=l+r>>1;
if(a<=mid) updata(l,mid,lson,a,b);
if(b>mid) updata(mid+1,r,rson,a,b);
pushup(x);
}
void modify(int l,int r,int x,int a,int b,int c)
{
if(a>b) return ;
if(a<=l&&r<=b)
{
s[x]=(r-l+1)*c;
return ;
}
pushdown(l,r,x);
int mid=l+r>>1;
if(a<=mid) modify(l,mid,lson,a,b,c);
if(b>mid) modify(mid+1,r,rson,a,b,c);
pushup(x);
}
void nxt0(int l,int r,int x,int a)
{
if(r<a||nxt<=l||s[x]==r-l+1) return ;
if(l==r)
{
nxt=l;
return ;
}
int mid=l+r>>1;
pushdown(l,r,x);
nxt0(l,mid,lson,a),nxt0(mid+1,r,rson,a);
}
void nxt1(int l,int r,int x,int a)
{
if(r<a||nxt<=l||!s[x]) return ;
if(l==r)
{
nxt=l;
return ;
}
int mid=l+r>>1;
pushdown(l,r,x);
nxt1(l,mid,lson,a),nxt1(mid+1,r,rson,a);
}
int query(int l,int r,int x,int a)
{
if(l==r) return s[x];
pushdown(l,r,x);
int mid=l+r>>1;
if(a<=mid) return query(l,mid,lson,a);
return query(mid+1,r,rson,a);
}
int rd()
{
int ret=0,f=1; char gc=getchar();
while(gc<'0'||gc>'9') {if(gc=='-') f=-f; gc=getchar();}
while(gc>='0'&&gc<='9') ret=ret*10+gc-'0',gc=getchar();
return ret*f;
}
int main()
{
n=rd(),rd(),rd(),rd();
int i;
for(i=1;i<=n;i++)
{
if(rd()==1)
{
A=rd(),B=rd(),f=1,len=0;
if(!A) continue;
if(A<0) f=-1,A=-A;
while(A) p[len++]=(A&1)*f,A>>=1;
p[len++]=0,p[len]=0,updata(0,N,1,B,B+len-1);
if(p[len]>0)
{
nxt=1<<30,nxt0(0,N,1,B+len);
modify(0,N,1,B+len,nxt-1,0),modify(0,N,1,nxt,nxt,1);
}
if(p[len]<0)
{
nxt=1<<30,nxt1(0,N,1,B+len);
modify(0,N,1,B+len,nxt-1,1),modify(0,N,1,nxt,nxt,0);
}
}
else A=rd(),printf("%d\n",query(0,N,1,A));
}
return 0;
}
//10 3 1 2 1 100 0 1 2333 0 1 -233 0 2 5 2 7 2 15 1 5 15 2 15 1 -1 12 2 15

【BZOJ4942】[Noi2017]整数 线段树+DFS(卡过)的更多相关文章

  1. [BZOJ4942][Noi2017]整数 线段树+压位

    用线段树来模拟加减法过程,维护连续一段中是否全为0/1. 因为数字很大,我们60位压一位来处理. #include<iostream> #include<cstring> #i ...

  2. HDU 5692 线段树+dfs序

    Snacks Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Sub ...

  3. Tsinsen A1505. 树(张闻涛) 倍增LCA,可持久化线段树,DFS序

    题目:http://www.tsinsen.com/A1505 A1505. 树(张闻涛) 时间限制:1.0s   内存限制:512.0MB    总提交次数:196   AC次数:65   平均分: ...

  4. BZOJ_3252_攻略_线段树+dfs序

    BZOJ_3252_攻略_线段树+dfs序 Description 题目简述:树版[k取方格数] 众所周知,桂木桂马是攻略之神,开启攻略之神模式后,他可以同时攻略k部游戏.今天他得到了一款新游戏< ...

  5. 【XSY2534】【BZOJ4817】树点涂色 LCT 倍增 线段树 dfs序

    题目大意 ​ Bob有一棵\(n\)个点的有根树,其中\(1\)号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同.定义一条路径的权值是:这条路径上的点(包括起点和终点)共有多少种不同的颜 ...

  6. 【bzoj4817】树点涂色 LCT+线段树+dfs序

    Description Bob有一棵n个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同.定义一条路 径的权值是:这条路径上的点(包括起点和终点)共有多少种不同的颜色. ...

  7. S - Query on a tree HDU - 3804 线段树+dfs序

    S - Query on a tree HDU - 3804   离散化+权值线段树 题目大意:给你一棵树,让你求这棵树上询问的点到根节点直接最大小于等于val的长度. 这个题目和之前写的那个给你一棵 ...

  8. [Bzoj4942][Noi2017]整数(线段树)

    4942: [Noi2017]整数 Time Limit: 50 Sec  Memory Limit: 512 MBSubmit: 363  Solved: 237[Submit][Status][D ...

  9. BZOJ4942 NOI2017整数(线段树)

    首先把每32位压成一个unsigned int(当然只要压起来能过就行).如果不考虑进/退位的话,每次只要将加/减上去的数拆成两部分直接单点修改就好了.那么考虑如何维护进/退位.可以发现进位的过程其实 ...

随机推荐

  1. 前端判断是否APP客户端打开触屏,实现跳转APP原生组件交互之遐想

    今天做了一个html的活动页面,本来马上就要完工,准备开开心心收尾,结果~... 产品突然提出需要说,要讲html中的某些交互和APP原生组件挂钩,心里一万头xxx奔过~ 静下心来思考 以往我们是判断 ...

  2. Java IO 学习(二)select/poll/epoll

    如上文所说,select/poll/epoll本质上都是同步阻塞的,但是由于实现了IO多路复用,在处理聊天室这种需要处理大量长连接但是每个连接上数据事件较少的场景时,相比最原始的为每个连接新开一个线程 ...

  3. POJ 3368 Frequent values 线段树与RMQ解法

    题意:给出n个数的非递减序列,进行q次查询.每次查询给出两个数a,b,求出第a个数到第b个数之间数字的最大频数. 如序列:-1 -1 1 1 1 1 2 2 3 第2个数到第5个数之间出现次数最多的是 ...

  4. php中int类型在不同平台所占不同字节数理解

    1.在不同平台上占字节数与最大值 在32位平台上int占4个字节,在64位平台上int占8个字节,PHP_INT_SIZE 在32位平台上int的最大值2^31 - 1,在64位平台上int最大值2^ ...

  5. Laravel 时间处理

    $info['date'] = $item->created_at->diffForHumans();//友好时间显示 $info['date'] = $item->created_ ...

  6. xamarin.android 资源图片问题

    在xamarin.android 中,关于图片的资源一般都在Resources.drawable下面,在Resources这个文件夹下面,包含了drawable.drawale-hdpi.drawab ...

  7. iscroll 子表左右滚动同时保持页面整体上下滚动

    if ( this.options.preventDefault && !utils.isBadAndroid && !utils.preventDefaultExce ...

  8. apache服务器日志及重启方法

    进入  lamp安装目录 ./ctlscript.sh restart 重启 实时查看日志 tail -f error_log 查看日志方法  404 及某天的方法cat access_log_201 ...

  9. Linux下测试PHP和MySQL是否正确安装

    测试PHP: 本打算这样配置: 1.拷贝PHP配置文件 cd /usr/local/php/etc cp php.ini /usr/local/php/lib/php.ini 2.修改apache配置 ...

  10. django网站搭建常用的一些代码

    from functools import wrapsdef check_user_login(func): @wraps(func) def return_wrapper(request, *arg ...