bzoj 5294: [Bjoi2018]二进制【动态dp+线段树】
不太清楚是不是动态dp……?
这个维护其实和最大连续子段差不多,维护l[x][y],r[x][y],m[x][y]分别表示包含左儿子的01个数为(x,y)的区间个数,包含右儿子的01个数为(x,y)的区间个数,和01个数为(x,y)的所有区间个数
x表示1的个数情况,0表示0个,1表示1个,2表示>=2的偶数个,3表示>=3的奇数个
y表示0的个数情况,0表示0个,1表示1个,2表示>=2个
转移的话合并ls.r,rs.l即可,注意是乘法,注意细节,转移很难写……
#include<iostream>
#include<cstdio>
using namespace std;
const int N=100005;
int n,m,a[N];
struct xds
{
long long l[4][3],r[4][3],m[4][3],s[2];
}t[N<<2];
int read()
{
int r=0,f=1;
char p=getchar();
while(p>'9'||p<'0')
{
if(p=='-')
f=-1;
p=getchar();
}
while(p>='0'&&p<='9')
{
r=r*10+p-48;
p=getchar();
}
return r*f;
}
int wk1(int x)
{
return (x<=1)?x:(x%2+2);
}
int wk0(int x)
{
return (x<=1)?x:2;
}
xds operator + (const xds &a,const xds &b)
{
xds c;
c.s[0]=a.s[0]+b.s[0];
c.s[1]=a.s[1]+b.s[1];
for(int i=0;i<=3;i++)
for(int j=0;j<=2;j++)
{
c.l[i][j]=a.l[i][j];
c.r[i][j]=b.r[i][j];
c.m[i][j]=a.m[i][j]+b.m[i][j];
}
for(int i=0;i<=3;i++)
for(int j=0;j<=2;j++)
if(a.r[i][j])
for(int k=0;k<=3;k++)
for(int l=0;l<=2;l++)
if(b.l[k][l])
c.m[wk1(i+k)][wk0(j+l)]+=a.r[i][j]*b.l[k][l];
for(int i=0;i<=3;i++)
for(int j=0;j<=2;j++)
{
c.l[wk1(a.s[1]+i)][wk0(a.s[0]+j)]+=b.l[i][j];
c.r[wk1(b.s[1]+i)][wk0(b.s[0]+j)]+=a.r[i][j];
}
return c;
}
void build(int ro,int l,int r)
{
if(l==r)
{
int x=(a[l]==1),y=(a[l]==0);
t[ro].s[0]=y,t[ro].s[1]=x;
t[ro].m[x][y]=t[ro].l[x][y]=t[ro].r[x][y]=1;
return;
}
int mid=(l+r)>>1;
build(ro<<1,l,mid);
build(ro<<1|1,mid+1,r);
t[ro]=t[ro<<1]+t[ro<<1|1];
}
void update(int ro,int l,int r,int p)
{
if(l==r)
{
int x=t[ro].s[1],y=t[ro].s[0];
t[ro].m[x][y]=t[ro].l[x][y]=t[ro].r[x][y]=0;
swap(t[ro].s[0],t[ro].s[1]);
t[ro].m[y][x]=t[ro].l[y][x]=t[ro].r[y][x]=1;
return;
}
int mid=(l+r)>>1;
if(p<=mid)
update(ro<<1,l,mid,p);
else
update(ro<<1|1,mid+1,r,p);
t[ro]=t[ro<<1]+t[ro<<1|1];
}
xds ques(int ro,int l,int r,int x,int y)
{
if(l==x&&r==y)
return t[ro];
int mid=(l+r)>>1;
if(y<=mid)
return ques(ro<<1,l,mid,x,y);
else if(x>mid)
return ques(ro<<1|1,mid+1,r,x,y);
else
return ques(ro<<1,l,mid,x,mid)+ques(ro<<1|1,mid+1,r,mid+1,y);
}
int main()
{
n=read();
for(int i=1;i<=n;i++)
a[i]=read();
build(1,1,n);
m=read();
while(m--)
{
int o=read();
if(o==1)
{
int x=read();
update(1,1,n,x);
}
else
{
int l=read(),r=read();
xds x=ques(1,1,n,l,r);
printf("%lld\n",x.m[0][0]+x.m[0][1]+x.m[0][2]+x.m[2][0]+x.m[2][1]+x.m[2][2]+x.m[3][2]);
}
}
return 0;
}
bzoj 5294: [Bjoi2018]二进制【动态dp+线段树】的更多相关文章
- [动态dp]线段树维护转移矩阵
背景:czy上课讲了新知识,从未见到过,总结一下. 所谓动态dp,是在动态规划的基础上,需要维护一些修改操作的算法. 这类题目分为如下三个步骤:(都是对于常系数齐次递推问题) 1先不考虑修改,不考虑区 ...
- luoguP4719 【模板】动态 DP 线段树+树链剖分+矩阵乘法+动态DP
题目描述 给定一棵n个点的树,点带点权. 有m次操作,每次操作给定x,y,表示修改点x的权值为y. 你需要在每次操作之后求出这棵树的最大权独立集的权值大小. 输入输出格式 输入格式: 第一行,n,m分 ...
- bzoj 5294: [Bjoi2018]二进制
Description pupil 发现对于一个十进制数,无论怎么将其的数字重新排列,均不影响其是不是333 的倍数.他想研究对于二进 制,是否也有类似的性质.于是他生成了一个长为n 的二进制串,希望 ...
- SP1716 GSS3 - Can you answer these queries III - 动态dp,线段树
GSS3 Description 动态维护最大子段和,支持单点修改. Solution 设 \(f[i]\) 表示以 \(i\) 为结尾的最大子段和, \(g[i]\) 表示 \(1 \sim i\) ...
- 【BZOJ3821/UOJ46】玄学(二进制分组,线段树)
[BZOJ3821/UOJ46]玄学(二进制分组,线段树) 题面 BZOJ UOJ 题解 呜,很好的题目啊QwQ. 离线做法大概可以线段树分治,或者直接点记录左右两次操作时的结果,两个除一下就可以直接 ...
- cf834D(dp+线段树区间最值,区间更新)
题目链接: http://codeforces.com/contest/834/problem/D 题意: 每个数字代表一种颜色, 一个区间的美丽度为其中颜色的种数, 给出一个有 n 个元素的数组, ...
- ZOJ 3349 Special Subsequence 简单DP + 线段树
同 HDU 2836 只不过改成了求最长子串. DP+线段树单点修改+区间查最值. #include <cstdio> #include <cstring> #include ...
- hdu 3016 dp+线段树
Man Down Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total S ...
- Codeforces Round #620 F2. Animal Observation (hard version) (dp + 线段树)
Codeforces Round #620 F2. Animal Observation (hard version) (dp + 线段树) 题目链接 题意 给定一个nm的矩阵,每行取2k的矩阵,求总 ...
随机推荐
- Windows-速度优化的几个方面
One. Win+R - > cmd- > msconfig 禁用不需要的启动项! Two. 关闭一些视觉选项 Three. 设置应用启动快捷键
- 【剑指offer】异或去重
转载请注明出处:http://blog.csdn.net/ns_code/article/details/27568975 这篇文章没有代码.介绍的是纯理论的思路. 异或是一种基于二进制的位运算,用符 ...
- java开始到熟悉63-65
本次内容:java常用类 1.包装类 package array; public class wrapperclass { public static void main(String[] args) ...
- 2014MadCon厦门分享会-笔记(下)
32 <如何与百度互动,不知道这些就不要做SEO了>百度站长平台资深产品运营师 曹丽丽(飞鸟) 33 注意百度站长平台的提醒.如果你不留电话,不留其他联系方式,出问题了,百度怎么提醒你呢? ...
- 创建一个zookeeper的会话(实现watcher)
在先前的章节中,我们利用zkCli去了解了一下主要的zookeeper的操作.在接下来的章节中,我们将会学习一下在应用中是怎样利用zookeeper的api的.接下来我们将利用一个程序展示一下,怎样来 ...
- Linux安装程序Anaconda分析(续)
本来想写篇关于Anaconda的文章,但看到这里写的这么详细,转,原文在这里:Linux安装程序Anaconda分析(续) (1) disptach.py: 下面我们看一下Dispatcher类的主要 ...
- WM_GETMINMAXINFO的作用 .
如果想要实现窗口全屏,并且还有状态栏,会出现问题,那就是OnGetMinMaxInfo函数的作用.你可以试一下,如果把这个函数去掉,则当你按下工具栏中的全屏显示按钮时,框架视图确实变大了,但没有想象的 ...
- 编写自定义PE结构的程序(如何手写一个PE,高级编译器都是编译好的PE头部,例如MASM,TASM等,NASM,FASM是低级编译器.可以自定义结构)
正在学PE结构...感谢个位大哥的文章和资料...这里先说声谢谢 一般高级编译器都是编译好的PE头部,例如MASM,TASM等一直都说NASM,FASM是低级编译器.可以自定义结构但是苦于无人发布相关 ...
- python 2: 解决python中的plot函数的图例legend不能显示中文问题
问题: 图像标题.横纵坐标轴的标签都能显示中文名字,但是图例就是不能显示中文,怎么解决呢? 解决: plt.figure() plt.title(u'训练性能', fontproperties=f ...
- Android Studio解决导入项目非常慢
Android Studio比Eclipse ADT有巨大的优势.Android Studio原生支持使用Gradle来构建项目,使用动态语言Groovy定义项目构建的过程,避免了build.xml文 ...