[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)的 ...
随机推荐
- CTex+WinEdt10.2安装详细教程与破解
原文地址:https://www.cnblogs.com/xiachongkun/p/8176390.html Latex作为目前最好用的文档编排工具,以前只是简单会一点,现在也已经忘得差不多了.因为 ...
- 【原创】大叔问题定位分享(32)mysql故障恢复
mysql启动失败,一直crash,报错如下: 2019-03-14T11:15:12.937923Z 0 [Note] InnoDB: Uncompressed page, stored check ...
- [JavaScript]使用ArrayBuffer和Blob编辑二进制流
Blob()构造方法返回一个新的Blob对象. 内容是包含参数array的二进制字节流. 语法 var aBlob = new Blob( array, options ); 参数 array is ...
- Boostrap轮图片可以左右滑动
记得引用Boostrap的js和css html代码: <div id="Mycarousel" class="carousel slide col-md-12&q ...
- 驳2B文 "我为什么放弃Go语言"
此篇文章流传甚广, 其实里面没啥干货, 而且里面很多观点是有问题的. 这个文章在 golang-china 很早就讨论过了. 最近因为 Rust 1.0 和 1.1 的发布, 导致这个文章又出来毒 ...
- Android之androidmainfest.xml配置文件详解
写配置文件的时候我们会不知道把那些配置项放在哪里,请看: 配置文件样例: <?xml version="1.0" encoding="utf-8"?> ...
- 通过设置ie的通过跨域访问数据源,来访问本地服务
1.首先设置通过域访问数据源 设置通过域访问数据源 2.javascript脚本ajax使用本地服务登录(评价,人证的类似)接口 <html> <head> <scrip ...
- 使用open live writer客户端写博客
注:Windows Live Writer 已经停止更新,建议安装 Open Live Writer,下载地址: http://openlivewriter.org/ 使用open live writ ...
- Confluence 6 通过 SSL 或 HTTPS 运行 - 创建或请求一个 SSL 证书
在启用 HTTPS 之前,你需要一个有效的证书,如果你已经有了一个有效的证书,你可以直接跳过这个步骤,进入 step 2. 你可以创建一个自签名的证书,或者从信任的 Certificate Autho ...
- Confluence 6 使用 Decorator 宏
Decorator 宏(Macros)是 Velocity 宏.这个宏可以被用来在页面编辑 Custom decorators 中创建复杂或者可变的部分,例如菜单,页面其他部分等.Decorator ...