[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)的 ...
随机推荐
- oracle procedure存储过程
1.基本结构 CREATE OR REPLACE PROCEDURE 存储过程名字 ( 参数1 IN NUMBER, 参数2 IN NUMBER ) IS/AS 变量1 ; 变量2 DATE: BEG ...
- [转] Git + LaTeX workflow
本文取自 https://stackoverflow.com/questions/6188780/git-latex-workflow 感谢 abcd@stackoverflow Changes to ...
- 写markdown博客如何将截图快速上传到图床——记一个工具插件的实现(windows版 开源)
打造一个上传图片到图床利器的插件(Mac版 开源)(2018-06-24 19:44) 更新于2018年2月 做了以下改动: 1.修复了一个bug,把服务器区域做成可配: 七牛有华北,华东,华南以及美 ...
- MicroPython的开发板
比如: pyboard micro:bit ESP8266/ESP32 stm32等等 什么是pyboard? pyboard是官方的MicroPython微控制器板,完全支持软件功能.硬件有: ST ...
- JavaScript 删除某个数组中指定的对象
返回对象在数组中的下标: _arr表示一个Array数组,里面包括了很多的对象如下图: _obj表示某一个数组对象 function getIndex (_arr,_obj) { var le ...
- Python-Mongodb vs mysql
mongodb https://www.cnblogs.com/kermitjam/articles/10147254.html#_label5 centos安装mongodb: https://bl ...
- 关于const修饰指针
const修饰指针,一般分为如下四种情况: int b = 500; const int *a = &b; //情况1 int const *a = &b // 2 ...
- Ubuntu16.04配置Tomcat的80端口访问
[问题描述] 在阿里云 ECS 服务器 Ubuntu16.04 下部署 Java Web 应用时,发现配置的 Tomcat 服务启动后 80 端口无法被监听. [问题原因] 出现该问题的主要原因是:非 ...
- requests 的基本用法
r = requests.get('www.baidu.com') r.request.headers{'User-Agent': 'python-requests/2.18.4', 'Accept- ...
- LeetCode(109):有序链表转换二叉搜索树
Medium! 题目描述: 给定一个单链表,其中的元素按升序排序,将其转换为高度平衡的二叉搜索树. 本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1. 示例: ...