loj #3146. 「APIO 2019」路灯
Posted encodetalker
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了loj #3146. 「APIO 2019」路灯相关的知识,希望对你有一定的参考价值。
loj #3146. 「APIO 2019」路灯
暴力的话就是查询\((l,r)\)之间是否全部是1,考虑如何优化查询
我们可以利用\(set\)来维护每一个全\(1\)区间和它出现的时间,具体的,用\((lp,rp,l,r)\)来表示\((lp,rp)\)的全\(1\)区间在时间\([l,r]\)中是存在的
那么对于一个在时间\(i\)的询问\((l_i,r_i)\),\((lp,rp,l,r)\)会对它产生贡献当且仅当\(lp\leq l_i,rp\geq r_i,i\geq l\),产生的贡献为\(min(i,r)-l+1\)
注意到限制的条件其实是类似于三维偏序的,将全\(1\)区间的四元组也当做询问,我们按照\(r\)值降序所有的询问,进行\(cdq\)分治
考虑前一半对后一半的贡献,两边分别按\(l\)升序排序,线段树维护这个类似区间长度的贡献即可
细节稍微有点小多,而且由于过度使用stl所以常数巨大
#include<iostream>
#include<string.h>
#include<string>
#include<stdio.h>
#include<algorithm>
#include<vector>
#include<math.h>
#include<queue>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
typedef long double db;
const int N=10000;
const db pi=acos(-1.0);
#define lowbit(x) (x)&(-x)
#define sqr(x) (x)*(x)
#define rep(i,a,b) for (register int i=a;i<=b;i++)
#define per(i,a,b) for (register int i=a;i>=b;i--)
#define fir first
#define sec second
#define mp(a,b) make_pair(a,b)
#define pb(a) push_back(a)
#define maxd 998244353
#define eps 1e-8
struct segnode
int lp,rp,l,r;
seg[1200100];
struct qnode
int l,r,tim,id;
q[300300];
struct tnode
int op,id,r;
th[2002000];
int ans[300300];
int n,m,nowr[300300],id[300300],tot=0,sta[300300];
int tr[2002000],add[2002000],qtot=0,tot1=0;
set<int> nowl;
set<int>::iterator iter;
char s[300300],op[10];
int read()
int x=0,f=1;char ch=getchar();
while ((ch<'0') || (ch>'9')) if (ch=='-') f=-1;ch=getchar();
while ((ch>='0') && (ch<='9')) x=x*10+(ch-'0');ch=getchar();
return x*f;
void pushup(int id) tr[id]=tr[id<<1]+tr[id<<1|1];
void pushdown(int id,int l,int r)
if (add[id])
int mid=(l+r)>>1;
tr[id<<1]+=add[id]*(mid-l+1);
tr[id<<1|1]+=add[id]*(r-mid);
add[id<<1]+=add[id];add[id<<1|1]+=add[id];
add[id]=0;
void modify(int id,int l,int r,int ql,int qr,int val)
//cout << l << " " << r << " " << ql << " " << qr << " " << val << endl;
if ((l>=ql) && (r<=qr))
tr[id]+=val*(r-l+1);
add[id]+=val;return;
pushdown(id,l,r);
int mid=(l+r)>>1;
if (ql<=mid) modify(id<<1,l,mid,ql,qr,val);
if (qr>mid) modify(id<<1|1,mid+1,r,ql,qr,val);
pushup(id);
int query(int id,int l,int r,int ql,int qr)
if ((l>=ql) && (r<=qr)) return tr[id];
int mid=(l+r)>>1,ans=0;pushdown(id,l,r);
if (ql<=mid) ans+=query(id<<1,l,mid,ql,qr);
if (qr>mid) ans+=query(id<<1|1,mid+1,r,ql,qr);
return ans;
bool cmp1(tnode p,tnode q)
if (p.r!=q.r) return p.r>q.r;
else return p.op<q.op;
bool cmp2(tnode x,tnode y)
if (x.op!=y.op) return x.op<y.op;
else if (x.op==1) return seg[x.id].lp<seg[y.id].lp;
else return q[x.id].l<q[y.id].l;
void solve(int l,int r)
if (l==r) return;
int mid=(l+r)>>1;
solve(l,mid);solve(mid+1,r);
sort(th+l,th+mid+1,cmp2);
sort(th+mid+1,th+r+1,cmp2);
int p=l;
rep(i,mid+1,r)
if (th[i].op==1) continue;
while ((p<=mid) && (th[p].op==1) && (q[th[i].id].l>=seg[th[p].id].lp))
modify(1,1,m,seg[th[p].id].l,seg[th[p].id].r,1);
p++;
ans[th[i].id]+=query(1,1,m,1,q[th[i].id].tim);
rep(i,l,p-1) modify(1,1,m,seg[th[i].id].l,seg[th[i].id].r,-1);
int main()
n=read();m=read();
scanf("%s",s+1);
rep(i,1,n) sta[i]=s[i]-'0';
for (int i=1;i<=n;i++)
if (sta[i]==0) continue;
int j=i;
while ((j<=n) && (sta[j]==1)) j++;j--;
nowr[i]=j;nowl.insert(i);
id[i]=(++tot);
seg[id[i]]=(segnode)i,j,1,m;i=j;
//for (iter=nowl.begin();iter!=nowl.end();iter++) cout << (*iter) << " ";cout << endl;
//rep(i,1,n) cout << nowr[i] << " ";cout << endl;
rep(i,1,m)
scanf("%s",op);
if (op[0]=='t')
if (i==m) continue;
int pos=read();sta[pos]^=1;
if (sta[pos])
int l=pos,r=pos;
iter=nowl.upper_bound(pos);
if (iter!=nowl.end())
int tmp=(*iter);
if (tmp==pos+1)
r=nowr[tmp];
seg[id[tmp]].r=i;nowl.erase(tmp);
iter=nowl.lower_bound(pos);
if (iter!=nowl.begin())
int tmp=*(--iter);
if (nowr[tmp]==pos-1)
l=tmp;
seg[id[tmp]].r=i;
nowl.erase(tmp);
id[l]=(++tot);nowr[l]=r;
seg[id[l]]=(segnode)l,r,i+1,m;
nowl.insert(l);
else
iter=nowl.upper_bound(pos);iter--;
int l=(*iter),r=nowr[l];
seg[id[l]].r=i;
if (l<pos)
id[l]=(++tot);
seg[id[l]]=(segnode)l,pos-1,i+1,m;
nowr[l]=pos-1;
else nowl.erase(l);
if (r>pos)
id[pos+1]=(++tot);
seg[id[pos+1]]=(segnode)pos+1,r,i+1,m;
nowr[pos+1]=r;nowl.insert(pos+1);
else
q[++qtot].id=qtot;q[qtot].tim=i;
q[qtot].l=read();q[qtot].r=read()-1;
//rep(i,1,qtot) cout << q[i].id << " " << q[i].l << " " << q[i].r << " " << q[i].tim << endl;
rep(i,1,tot) th[++tot1]=(tnode)1,i,seg[i].rp;
rep(i,1,qtot) th[++tot1]=(tnode)2,i,q[i].r;
sort(th+1,th+1+tot1,cmp1);
//rep(i,1,tot1) cout << th[i].id << " " << th[i].op << " " << th[i].r << endl;
solve(1,tot1);
rep(i,1,qtot) printf("%d\n",ans[i]);
return 0;
/*
5 8
11011
query 1 2
query 1 2
query 1 6
query 3 4
toggle 3
query 3 4
toggle 2
query 1 6
*/
以上是关于loj #3146. 「APIO 2019」路灯的主要内容,如果未能解决你的问题,请参考以下文章
luoguP5445 [APIO2019]路灯 树套树+set