[娱乐向] ABC 381 E 莫队做法
极其抽象,开始就想偏了,没有瞪出来咋做所以我用了莫队
记
对于一个询问
那么它的答案就是
我瞪了30分钟,没啥发现
所以直接暴力拆开
如果左边小
移项过后是:
发现对于询问来说右边是常量
第二种情况同理
所以对于一个询问,我们分别可以维护两颗线段树
存储的下标都是
按照式子,分别在线段树中找到下标分别大于和小于
两者取max即可
然后发现
可以
然后把它搞成莫队就可以了
有
细节巨多,在90多分钟的时候才过,没时间看
#include<bits/stdc++.h>
using namespace std;
constexpr int N = 1e5+99;
int n, Q, maxn;
int c[N];
long long sum;
int cnt[N];
char str[N];
long long ans1[N], ans2[N];
struct query {
int l, r, id;
bool operator<(const query &x) const {
if (l / maxn != x.l / maxn) return l < x.l;
return (l / maxn) & 1 ? r < x.r : r > x.r;
}
} a[N];
int sum1[N],sum2[N];
struct BIT1 {
int tree[4*N];
void build(int bh,int l,int r) {
if(l==r) {
tree[bh]=1e8;
} else {
int mid=(l+r)/2;
build(bh*2,l,mid),build(bh*2+1,mid+1,r);
tree[bh]=min(tree[bh*2],tree[bh*2+1]);
}
}
void update(int bh,int l,int r,int x,int y) {
if(l==r) {
tree[bh]=y;
} else {
int mid=(l+r)/2;
if(x<=mid) update(bh*2,l,mid,x,y);
else update(bh*2+1,mid+1,r,x,y);
tree[bh]=min(tree[bh*2],tree[bh*2+1]);
}
}
int query(int bh,int l,int r,int L,int R) {
if(L<=l&&r<=R) {
return tree[bh];
} else {
int mid=(l+r)/2,oo=1e8;
if(L<=mid) oo=min(oo,query(bh*2,l,mid,L,R));
if(R>mid) oo=min(oo,query(bh*2+1,mid+1,r,L,R));
return oo;
}
}
} T1;
struct BIT2 {
int tree[4*N];
void build(int bh,int l,int r) {
if(l==r) {
tree[bh]=0;
} else {
int mid=(l+r)/2;
build(bh*2,l,mid),build(bh*2+1,mid+1,r);
tree[bh]=max(tree[bh*2],tree[bh*2+1]);
}
}
void update(int bh,int l,int r,int x,int y) {
if(l==r) {
tree[bh]=y;
} else {
int mid=(l+r)/2;
if(x<=mid) update(bh*2,l,mid,x,y);
else update(bh*2+1,mid+1,r,x,y);
tree[bh]=max(tree[bh*2],tree[bh*2+1]);
}
}
int query(int bh,int l,int r,int L,int R) {
if(L<=l&&r<=R) {
return tree[bh];
} else {
int mid=(l+r)/2,oo=0;
if(L<=mid) oo=max(oo,query(bh*2,l,mid,L,R));
if(R>mid) oo=max(oo,query(bh*2+1,mid+1,r,L,R));
return oo;
}
}
} T2;
int gs=0;
#define pii pair<int,int>
set<pii>st1[N],st2[N];
void add(int i) {
if(str[i]=='/') {
gs++;
st1[sum2[i]+sum1[i-1]].insert(make_pair(sum2[i],i));
st2[sum2[i]+sum1[i-1]].insert(make_pair(-sum1[i-1],i));
auto g1=st1[sum2[i]+sum1[i-1]].begin();
int upd1=1e8,upd2=0;
if(g1!=st1[sum2[i]+sum1[i-1]].end()) {
upd1=g1->first;
}
auto g2=st2[sum2[i]+sum1[i-1]].begin();
if(g2!=st2[sum2[i]+sum1[i-1]].end()) {
upd2=g2->first;
upd2=-upd2;
}
T1.update(1,0,n,sum2[i]+sum1[i-1],upd1);
T2.update(1,0,n,sum2[i]+sum1[i-1],upd2);
}
}
void del(int i) {
if(str[i]=='/') {
gs--;
auto v1=st1[sum2[i]+sum1[i-1]].lower_bound(make_pair(sum2[i],i));
st1[sum2[i]+sum1[i-1]].erase(v1);
auto v2=st2[sum2[i]+sum1[i-1]].lower_bound(make_pair(-sum1[i],i));
st2[sum2[i]+sum1[i-1]].erase(v2);
auto g1=st1[sum2[i]+sum1[i-1]].begin();
int upd1=1e8,upd2=0;
if(g1!=st1[sum2[i]+sum1[i-1]].end()) {
upd1=g1->first;
}
auto g2=st2[sum2[i]+sum1[i-1]].begin();
if(g2!=st2[sum2[i]+sum1[i-1]].end()) {
upd2=g2->first;
upd2=-upd2;
}
T1.update(1,0,n,sum2[i]+sum1[i-1],upd1);
T2.update(1,0,n,sum2[i]+sum1[i-1],upd2);
}
}
int ans[1000008];
int main() {
cin >> n >> Q;
maxn = sqrt(n);
scanf("%s",str+1);
T1.build(1,0,n);
T2.build(1,0,n);
for(int i=1; i<=n; i++) {
sum1[i]=sum1[i-1]+(str[i]=='1');
sum2[i]=sum2[i-1]+(str[i]=='2');
}
for (int i = 0; i < Q; i++) cin >> a[i].l >> a[i].r, a[i].id = i;
sort(a, a + Q);
for (int i = 0, l = 1, r = 0; i < Q; i++) {
while (l > a[i].l) add(--l);
while (r < a[i].r) add(++r);
while (l < a[i].l) del(l++);
while (r > a[i].r) del(r--);
ans[a[i].id]=0;
if(gs) {
ans[a[i].id]=max(ans[a[i].id],(sum2[a[i].r]-T1.query(1,0,n,sum1[a[i].l-1]+sum2[a[i].r],n))*2+1);
ans[a[i].id]=max(ans[a[i].id],(T2.query(1,0,n,0,sum1[a[i].l-1]+sum2[a[i].r])-sum1[a[i].l-1])*2+1);
}
}
for (int i = 0; i < Q; i++) {
cout<<ans[i]<<"\n";
}
return 0;
}