每个时刻都形成若干段满足段内任意两点可达。将其视为若干正方形。则查询相当于求历史上某点被正方形包含的时刻数量。并且注意到每个时刻只有O(1)个正方形出现或消失,那么求出每个矩形的出现时间和消失时间,就是裸的三维偏序,cdq分治+树状数组即可。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 1000000010
#define N 300010
#define mp(x,y) make_pair((x),(y))
#define fi first
#define se second
#define time se.fi
#define ans se.se
#define val se.se
#define left fi.fi
#define right fi.se
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
int x=0,f=1;char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return x*f;
}
typedef pair<int,int> pii;
typedef pair<pii,pii> ppp;
int n,m,t,u,v,a[N],tree[N];
char s[N];
set<ppp> seg;
ppp b[N<<1],q[N];
pii o;
struct data
{
ppp x;int op;
bool operator <(const data&a) const
{
return x.time<a.x.time||x.time==a.x.time&&x.fi<a.x.fi||x.time==a.x.time&&x.fi==a.x.fi&&op<a.op;
}
}c[N*3],d[N*3];
void add(int k,int x){while (k<=n) tree[k]+=x,k+=k&-k;}
int query(int k){int s=0;while (k) s+=tree[k],k-=k&-k;return s;}
void solve(int l,int r)
{
if (l==r) return;
int mid=l+r>>1;
solve(l,mid);
solve(mid+1,r);
int cur=l-1;
for (int i=mid+1;i<=r;i++)
if (c[i].op==1)
{
while (cur<mid&&(c[cur+1].op==1||c[cur+1].x.left<=c[i].x.left))
{
cur++;
if (c[cur].op==0) add(c[cur].x.right,c[cur].x.val);
}
c[i].x.ans+=query(c[i].x.right);
}
for (;cur>=l;cur--) if (c[cur].op==0) add(c[cur].x.right,-c[cur].x.val);
int i=l,j=mid+1;
for (int k=l;k<=r;k++)
if (i<=mid&&(j>r||c[i].x.left<c[j].x.left)) d[k]=c[i++];else d[k]=c[j++];
for (int k=l;k<=r;k++) c[k]=d[k];
}
signed main()
{
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
#endif
n=read(),m=read();
scanf("%s",s+1);
for (int i=1;i<=n;i++) a[i]=s[i]-'0';
if (!a[1]) seg.insert(mp(o,o));
for (int i=1;i<=n;i++)
if (a[i])
{
int t=i;
while (t<n&&a[t+1]==1) t++;
seg.insert(mp(mp(i-1,t),o));
i=t;
}
else if (!a[i+1]) seg.insert(mp(mp(i,i),o));
for (int i=1;i<=m;i++)
{
/*for (auto it=seg.begin();it!=seg.end();it++)
cout<<(*it).left<<' '<<(*it).right<<' '<<(*it).time<<endl;
cout<<endl;*/
char c=getc();
if (c=='q')
{
int l=read()-1,r=read()-1;
q[++t]=mp(mp(l,r),mp(i-1,0));
auto it=seg.upper_bound(mp(mp(l,n+1),o));
if (it!=seg.begin())
{
it--;
if ((*it).right>=r) q[t].ans=i-(*it).time;
}
}
else
{
int x=read();
if (a[x])
{
auto it=seg.lower_bound(mp(mp(x,0),o));it--;
ppp tmp=*it;seg.erase(it);
b[++u]=mp(tmp.fi,mp(i-1,i-tmp.time));
seg.insert(mp(mp(tmp.left,x-1),mp(i,0)));
seg.insert(mp(mp(x,tmp.right),mp(i,0)));
}
else
{
auto it=seg.lower_bound(mp(mp(x,0),o));
auto it2=it;it2--;
ppp tmp=*it;seg.erase(it);
ppp tmp2=*it2;seg.erase(it2);
b[++u]=mp(tmp.fi,mp(i-1,i-tmp.time));
b[++u]=mp(tmp2.fi,mp(i-1,i-tmp2.time));
seg.insert(mp(mp(tmp2.left,tmp.right),mp(i,0)));
}
a[x]^=1;
}
}
n++;
for (int i=1;i<=t;i++) q[i].right=n-q[i].right;
for (int i=1;i<=u;i++) b[i].right=n-b[i].right;
/*for (int i=1;i<=t;i++) cout<<q[i].left<<' '<<q[i].right<<' '<<q[i].time<<' '<<q[i].ans<<endl;
cout<<endl;
for (int i=1;i<=u;i++) cout<<b[i].left<<' '<<b[i].right<<' '<<b[i].time<<' '<<b[i].val<<endl;*/
//求left<=q[i].left right<=q[i].right time<=q[i].time 的权值和
/*for (int i=1;i<=t;i++)
for (int j=1;j<=u;j++)
if (b[j].left<=q[i].left&&b[j].right<=q[i].right&&b[j].time<=q[i].time) q[i].ans+=b[j].val;*/
for (int i=1;i<=t;i++) c[++v].x=q[i],c[v].op=1;
for (int i=1;i<=u;i++) c[++v].x=b[i],c[v].op=0;
sort(c+1,c+v+1);
solve(1,v);
sort(c+1,c+v+1);
for (int i=1;i<=v;i++) if (c[i].op==1) printf("%d\n",c[i].x.ans);
return 0;
//NOTICE LONG LONG!!!!!
}

  

LOJ3146 APIO2019路灯(cdq分治+树状数组)的更多相关文章

  1. 【BZOJ4553】[Tjoi2016&Heoi2016]序列 cdq分治+树状数组

    [BZOJ4553][Tjoi2016&Heoi2016]序列 Description 佳媛姐姐过生日的时候,她的小伙伴从某宝上买了一个有趣的玩具送给他.玩具上有一个数列,数列中某些项的值可能 ...

  2. BZOJ 1176 Mokia CDQ分治+树状数组

    1176: [Balkan2007]Mokia Time Limit: 30 Sec  Memory Limit: 162 MBSubmit: 1854  Solved: 821[Submit][St ...

  3. 【bzoj3262】陌上花开 CDQ分治+树状数组

    题目描述 有n朵花,每朵花有三个属性:花形(s).颜色(c).气味(m),又三个整数表示.现要对每朵花评级,一朵花的级别是它拥有的美丽能超过的花的数量.定义一朵花A比另一朵花B要美丽,当且仅当Sa&g ...

  4. 【bzoj2225】[Spoj 2371]Another Longest Increasing CDQ分治+树状数组

    题目描述 给定N个数对(xi, yi),求最长上升子序列的长度.上升序列定义为{(xi, yi)}满足对i<j有xi<xj且yi<yj. 样例输入 8 1 3 3 2 1 1 4 5 ...

  5. BZOJ 2683 简单题 cdq分治+树状数组

    题意:链接 **方法:**cdq分治+树状数组 解析: 首先对于这道题,看了范围之后.二维的数据结构是显然不能过的.于是我们可能会考虑把一维排序之后还有一位上数据结构什么的,然而cdq分治却可以非常好 ...

  6. BZOJ 4553 [Tjoi2016&Heoi2016]序列 ——CDQ分治 树状数组

    考虑答案的构成,发现是一个有限制条件的偏序问题. 然后三个维度的DP,可以排序.CDQ.树状数组各解决一维. #include <map> #include <cmath> # ...

  7. BZOJ1176---[Balkan2007]Mokia (CDQ分治 + 树状数组)

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1176 CDQ第一题,warush了好久.. CDQ分治推荐论文: 1 <从<C ...

  8. Hdu4742-Pinball Game 3D(cdq分治+树状数组)

    Problem Description RD is a smart boy and excel in pinball game. However, playing common 2D pinball ...

  9. hdu 5126 stars cdq分治套cdq分治+树状数组

    题目链接 给n个操作, 第一种是在x, y, z这个点+1. 第二种询问(x1, y1, z1). (x2, y2, z2)之间的总值. 用一次cdq分治可以将三维变两维, 两次的话就变成一维了, 然 ...

随机推荐

  1. 洛谷 P1281 书的复制 题解

    P1281 书的复制 题目背景 大多数人的错误原因:尽可能让前面的人少抄写,如果前几个人可以不写则不写,对应的人输出0 0. 不过,已经修改数据,保证每个人都有活可干. 题目描述 现在要把m本有顺序的 ...

  2. node.js切换多个版本

    开言 试用场景就是我们开发项目的时候,有可能一个项目需要v10版本,另一个项目需要v8版本,遇到这种问题,我们不能卸载再重新安装对应的版本去开发,遇到这样的问题的时候,那我们就可以去用另一种方式去切换 ...

  3. MSSQL手工注入 报错注入方法

    例子:www.kfgtfcj.gov.cn/lzygg/Zixun_show.aspx?id=1[1]首先爆版本:http://www.kfgtfcj.gov.cn/lzygg/Zixun_show. ...

  4. rsync实时同步

    假设有如下需求: 假设两个服务器: 192.168.0.1 源服务器  有目录 /opt/test/ 192.168.0.2 目标服务器  有目录 /opt/bak/test/ 实现的目的就是保持这两 ...

  5. Linux 磁盘的分区

    如果我们想在系统中新增一块硬盘,需要做什么呢? 1. 对磁盘进行分区,新建可用分区 2. 对该分区进行格式化,以创建系统可用的文件系统 3. 若想要仔细一点,可以对刚才新建好的文件系统进行检验 4. ...

  6. nginx 二级目录反向代理

    location /faceapi/ { #default_type application/json; # return 200 '{"status":"success ...

  7. JdkDynamicAopProxy与CglibAopProxy介绍

    继续上一篇的介绍 1.上一篇分析到createAopProxy方法,创建Aop代理对象 protected final synchronized AopProxy createAopProxy() { ...

  8. https://www.cnblogs.com/LBSer/p/3310455.html

    https://www.cnblogs.com/LBSer/p/3310455.html

  9. oracle系列九 SET运算符查询

    将多个查询用 SET 操作符连接组成一个新的查询 UNION/UNION ALL INTERSECT MINUS 排序:ORDER BY UNION 操作符 UNION 操作符返回两个查询的结果集的并 ...

  10. 从Linux服务器下载文件夹到本地

    从Linux服务器下载文件夹到本地 1.使用scp命令 scp /home/work/source.txt work@192.168.0.10:/home/work/ #把本地的source.txt文 ...