[Bjoi2018]二进制
题解:
首先发现性质
只有1个1的区间 或者 奇数个1且0的个数少于2这个区间是不合法的
然后这个东西暴力是比较好处理的
刚开始写的比较傻逼,分几种情况
先把0,1缩在一起
1.k1个0+1+k2个0
2.k1个1+0+k2个1 其中k1+k2是奇数
3.1之内单独1
4.0+奇数1
然后这样挺烦的
最讨厌写这种很容易漏掉的分类套路了。。
代码:
#include <bits/stdc++.h>
using namespace std;
#define rint register int
#define IL inline
#define dep(i,t,h) for (int i=t;i>=h;i--)
#define rep(i,h,t) for (int i=h;i<=t;i++)
#define ll long long
const int N=2e5;
int a[N],n,m,b[N],c[N],d[N],f[N];
IL ll js(int l)
{
ll cnt=; int jl=;
rep(k,,l) if (b[k]==) cnt++;
b[]=b[]^;
rep(k,,l)
if (b[k]!=b[k-]) c[++jl]=b[k],d[jl]=;
else d[jl]++;
rep(i,,jl)
if (c[i]==)
{
cnt+=f[d[i]];
if (i>) cnt+=(d[i]+)/;
if (i<jl) cnt+=(d[i]+)/;
}
d[]=d[jl+]=;
rep(i,,jl)
if (c[i]==)
{
if (d[i]==) cnt+=1ll*d[i-]*d[i+];
cnt+=max(d[i-]-,);
cnt+=max(d[i+]-,);
}
rep(i,,jl-)
if (c[i]==&&d[i]==)
{
cnt+=((d[i-]+)/)*(d[i+]/)+(d[i-]/)*((d[i+]+)/);
}
return 1ll*l*(l+)/-cnt;
}
int main()
{
ios::sync_with_stdio(false);
cin>>n;
rep(i,,n) cin>>a[i];
rep(i,,)
rep(j,,i)
if (j%==) f[i]+=i-j+;
cin>>m;
rep(i,,m)
{
int kk,x,y;
cin>>kk;
if (kk==)
{
cin>>x; a[x]^=;
} else
{
cin>>x>>y;
int len=y-x+;
rep(j,x,y) b[j-x+]=a[j];
cout<<js(len)<<endl;
}
}
return ;
}
我们考虑dp
$f[i][[6]$分别对应
0:0个0,奇数个1
1:0个0,偶数个0
2:1个0,奇数个0
3:1个0,偶数个0
4:1个1,任意0
5:0个1,任意0
写之前觉得挺烦的 写了发现好像挺好写 比上面那个不知道好写到哪里去了
然后因为带修改,所以是动态dp
链上动态dp用线段树
树上动态dp用动态链分治(怎么随便做做到这么多动态dp。。)
考虑用线段树维护
我们得再用一维 表示这个是左边还是右边还是全部
另外注意一下这样我们重复计数了 就是两种情况都满足的时候
所以我们要01/10 以及1单独出现的
但其实1单独出现的时候值是我们给的 所以直接给1不给2就行了
但我写之前没想这个所以给了2然后用树状数组再维护了一下1的个数
注意维护01/10的时候一个位置能影响两边
除了updata其他都是模板
updata只要思路清晰还是挺好写的
所以这东西好像并不难写??
代码:
#include <bits/stdc++.h>
using namespace std;
#define rint register int
#define IL inline
#define rep(i,h,t) for (int i=h;i<=t;i++)
#define dep(i,t,h) for (int i=t;i>=h;i--)
#define me(x) memset(x,0,sizeof(x))
#define ll long long
#define mid ((h+t)>>1)
#define lowbit(x) (x&(-x))
namespace IO{
char ss[<<],*A=ss,*B=ss;
IL char gc()
{
return A==B&&(B=(A=ss)+fread(ss,,<<,stdin),A==B)?EOF:*A++;
}
template<class T>void read(T &x)
{
rint f=,c; while (c=gc(),c<||c>) if (c=='-') f=-; x=(c^);
while (c=gc(),c>&&c<) x=(x<<)+(x<<)+(c^); x*=f;
}
char sr[<<],z[]; int Z,C=-;
template<class T>void wer(T x)
{
if (x<) sr[++C]='-',x=-x;
while (z[++Z]=x%+,x/=);
while (sr[++C]=z[Z],--Z);
}
IL void wer1()
{
sr[++C]=' ';
}
IL void wer2()
{
sr[++C]='\n';
}
template<class T>IL void maxa(T &x,T y) {if (x<y) x=y;}
template<class T>IL void mina(T &x,T y) {if (x>y) x=y;}
template<class T>IL T MAX(T x,T y) {return x>y?x:y;}
template<class T>IL T MIN(T x,T y) {return x<y?x:y;}
};
const int INF=1e9;
const int N=1e5+1e4;
using namespace IO;
vector<int> ve;
struct re{
ll a[][],b;
};
struct sgt{
ll f[N*][][],g[N*];
re updata(ll x[][],ll y[][])
{
ll g[][]={},ans=;
ans+=x[][]*(y[][]+y[][]);
ans+=x[][]*(y[][]+y[][]);
ans+=x[][]*y[][];
ans+=x[][]*y[][];
ans+=x[][]*y[][];
ans+=x[][]*y[][];
g[][]=x[][]+x[][]*y[][]+x[][]*y[][];
g[][]=x[][]+x[][]*y[][]+x[][]*y[][];
g[][]=x[][]+x[][]*y[][]+x[][]*y[][]
+x[][]*y[][]+x[][]*y[][];
g[][]=x[][]+x[][]*y[][]+x[][]*y[][]
+x[][]*y[][]+x[][]*y[][];
g[][]=x[][]+x[][]*y[][]+x[][]*y[][];
g[][]=x[][]+x[][]*y[][];
g[][]=y[][]+y[][]*x[][]+y[][]*x[][];
g[][]=y[][]+y[][]*x[][]+y[][]*x[][];
g[][]=y[][]+y[][]*x[][]+y[][]*x[][]
+y[][]*x[][]+y[][]*x[][];
g[][]=y[][]+y[][]*x[][]+y[][]*x[][]
+y[][]*x[][]+y[][]*x[][];
g[][]=y[][]+y[][]*x[][]+y[][]*x[][];
g[][]=y[][]+y[][]*x[][];
g[][]=x[][]*y[][]+x[][]*y[][];
g[][]=x[][]*y[][]+x[][]*y[][];
g[][]=x[][]*y[][]+x[][]*y[][]
+x[][]*y[][]+x[][]*y[][];
g[][]=x[][]*y[][]+x[][]*y[][]
+x[][]*y[][]+x[][]*y[][];
g[][]=x[][]*y[][]+x[][]*y[][];
g[][]=x[][]*y[][];
re k;
memcpy(k.a,g,sizeof(g)); k.b=ans;
return k;
}
void change(int x,int h,int t,int pos,int k)
{
if (h==t)
{
if (k==)
{
rep(i,,)
{
f[x][i][]=f[x][i][]=;
f[x][i][]=f[x][i][]=f[x][i][]=f[x][i][]=;
}
g[x]=;
} else
{
rep(i,,)
{
f[x][i][]=f[x][i][]=;
f[x][i][]=f[x][i][]=f[x][i][]=f[x][i][]=;
}
g[x]=;
}
return;
}
if (pos<=mid) change(x*,h,mid,pos,k);
else change(x*+,mid+,t,pos,k);
re kk=updata(f[x*],f[x*+]);
memcpy(f[x],kk.a,sizeof(kk.a)); g[x]=kk.b+g[x*]+g[x*+];
}
void query(int x,int h,int t,int h1,int t1)
{
if (h1<=h&&t<=t1)
{
ve.push_back(x); return;
}
if (h1<=mid) query(x*,h,mid,h1,t1);
if (mid<t1) query(x*+,mid+,t,h1,t1);
}
ll query2(int x,int h,int t,int h1,int t1)
{
ve.clear();
query(x,h,t,h1,t1);
ll now[][],ans=;
for (int i=;i<ve.size();i++) ans+=g[ve[i]];
memcpy(now,f[ve[]],sizeof(f[ve[]]));
for (int i=;i<ve.size();i++)
{
re k=updata(now,f[ve[i]]);
memcpy(now,k.a,sizeof(k.a)); ans+=k.b;
}
return ans;
}
}S;
int a[N],n,m;
struct sgt2{
int sum[N];
IL void c(int x,int t) { for(;x<=n;x+=lowbit(x)) sum[x]+=t;};
IL int d(int x) {int ans=; for (;x>;x-=lowbit(x)) ans+=sum[x]; return ans;}
IL int q(int h,int t) {return d(t)-d(h-);}
}S1,S2;
int main()
{
read(n);
rep(i,,n) read(a[i]);
rep(i,,n)
{
S.change(,,n,i,a[i]);
if (a[i]==) S1.c(i,);
if (i!=n&&a[i]^a[i+]==) S2.c(i,);
}
read(m);
rep(i,,m)
{
int kk,x,y;
read(kk);
if (kk==)
{
read(x); read(y);
wer(1ll*(y-x+)*(y-x+)/-(S.query2(,,n,x,y)-S1.q(x,y)-S2.q(x,y-)));
wer2();
} else
{
read(x);
if (x!=n&&a[x]^a[x+]==) S2.c(x,-);
if (a[x]==) S1.c(x,-);
if (x!=&&a[x-]^a[x]==) S2.c(x-,-);
a[x]^=;
if (a[x]==) S1.c(x,);
if (x!=n&&a[x]^a[x+]==) S2.c(x,);
if (x!=&&a[x-]^a[x]==) S2.c(x-,);
S.change(,,n,x,a[x]);
}
}
fwrite(sr,,C+,stdout);
return ;
}
[Bjoi2018]二进制的更多相关文章
- 【BZOJ5294】[BJOI2018]二进制(线段树)
[BZOJ5294][BJOI2018]二进制(线段树) 题面 BZOJ 洛谷 题解 二进制串在模\(3\)意义下,每一位代表的余数显然是\(121212\)这样子交替出现的. 其实换种方法看,就是\ ...
- 2019.02.12 bzoj5294: [Bjoi2018]二进制(线段树)
传送门 题意简述: 给出一个长度为nnn的二进制串. 你需要支持如下操作: 修改每个位置:1变0,0变1 询问对于一个区间的子二进制串有多少满足重排之后转回十进制值为333的倍数(允许前导000). ...
- bzoj 5294: [Bjoi2018]二进制
Description pupil 发现对于一个十进制数,无论怎么将其的数字重新排列,均不影响其是不是333 的倍数.他想研究对于二进 制,是否也有类似的性质.于是他生成了一个长为n 的二进制串,希望 ...
- luogu P4428 [BJOI2018]二进制
luogu 先考虑怎样的二进制串才会被3整除.可以发现如果二进制位第\(0,2,4...2n\)位如果为\(1\),那么在模3意义下为1,如果二进制位第\(1,3,5...2n+1\)位如果为\(1\ ...
- BZOJ5294 BJOI2018 二进制 线段树
传送门 因为每一位\(\mod 3\)的值为\(1,2,1,2,...\),也就相当于\(1,-1,1,-1,...\) 所以当某个区间的\(1\)的个数为偶数的时候,一定是可行的,只要把这若干个\( ...
- BZOJ5294 [BJOI2018] 二进制 【线段树】
BJOI的题目感觉有点难写 题目分析: 首先推一波结论.接下来的一切都在模3意义下 现在我们将二进制位重组,不难发现的是2^0≡1,2^1≡2,2^2≡1,2^3≡2....所以我们考虑这样的式子 2 ...
- BZOJ5294 BJOI2018二进制(线段树)
二进制数能被3整除相当于奇数.偶数位上1的个数模3同余.那么如果有偶数个1,一定存在重排方案使其合法:否则则要求至少有两个0且至少有3个1,这样可以给奇数位单独安排3个1. 考虑线段树维护区间内的一堆 ...
- Bzoj5294/洛谷P4428 [Bjoi2018]二进制(线段树)
题面 Bzoj 洛谷 题解 考虑一个什么样的区间满足重组之后可以变成\(3\)的倍数.不妨设\(tot\)为一个区间内\(1\)的个数.如果\(tot\)是个偶数,则这个区间一定是\(3\)的倍数,接 ...
- bzoj 5294: [Bjoi2018]二进制【动态dp+线段树】
不太清楚是不是动态dp--? 这个维护其实和最大连续子段差不多,维护l[x][y],r[x][y],m[x][y]分别表示包含左儿子的01个数为(x,y)的区间个数,包含右儿子的01个数为(x,y)的 ...
随机推荐
- JavaScript中的this -- 好像很有道理版
函数调用 首先需要从函数的调用开始讲起. JS(ES5)里面有三种函数调用形式: func(p1, p2) obj.child.method(p1, p2) func.call(context, p1 ...
- python中常用模块
OS模块 python编程时,经常和文件.目录打交道,这是就离不了os模块.os模块包含普遍的操作系统功能,与具体的平台无关os.name()——判断现在正在实用的平台,Windows 返回 ‘nt' ...
- Control算法相关
Control算法相关 添加新的control算法官方指导教程. 创建一个控制器: 在文件control_config中添加新控制器的配置信息: 注册新控制器. 如何添加新的CAN卡. Apollo中 ...
- 在TOMCAT下配置工程的默认访问设置(转)
对工程的部署一般是将工程的压缩文件放在tomcat安装目录的webapps下,访问时通过键入:http://localhost:8080/xx(假定为本机访问,xx是部署时的应用工程的访问名字). 而 ...
- linux下使用命令模式去编译Qt程序
1.打开终端输入,qmake -v ,如果提示版本信息正,就可以编译程序了. 2.当前目录切换到程序源代码目录,cd /home/likewei/untitled2 3.生成untitled2.pro ...
- Mybatis--01
mybatis 封装jdbc访问代码的一个框架 (hibernate) ORM对象关系映射 SpringMVC:用来封装servlet的框架 (struts) Spring:体系整合框架,其他框架的 ...
- OpenCV中RGB和HSV转换的问题
1.一般情况下HSV模型各分量的取值范围为:H为0到360°,S为0到100%,V为0到255.但是在OpenCV中在由RGB转换到HSV的过程中,发现HSV中H为0到180°,S为0到255,V为0 ...
- MySQL MyISAM引擎转换为InnoDB操作记录
进入mysql命令行模式: # mysql -uroot -ppwd 1.查看mysql提供什么存储引擎: mysql> show engines; 2.查看mysql当前提供的默认存储引擎: ...
- iOS weak 内存释放问题
我们都知道weak 关键字可以解决内存不释放问题,但是使用上有些讲究. 看代码: import UIKit var str = "Hello, playground" class ...
- Codeforces 1045G AI robots [CDQ分治]
洛谷 Codeforces 简单的CDQ分治题. 由于对话要求互相看见,无法简单地用树套树切掉,考虑CDQ分治. 按视野从大到小排序,这样只要右边能看见左边就可以保证互相看见. 发现\(K\)固定,那 ...