http://cplusoj.com/d/senior/p/SS230928B
老套路了
考虑枚举0和2
m + j + m i n ( f a m − g a j , f b m − g b j ) \large m+j+min(fa_m-ga_j,fb_m-gb_j) m+j+min(fam−gaj,fbm−gbj)
然后拆一下min,再分情况讨论一下,移项合并相同的
以其中一种情况为例
f a m − g a j ≤ f b m − g b j → f a m − f b m ≤ g a j − g b j \large fa_m-ga_j\le fb_m-gb_j \to fa_m-fb_m\le ga_j-gb_j fam−gaj≤fbm−gbj→fam−fbm≤gaj−gbj
m + f a m + ( − g a j + j ) \large m+fa_m+(-ga_j+j) m+fam+(−gaj+j)
后面拿个ds维护即可
#include
using namespace std;
//#define int long long
inline 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<<1)+(x<<3)+(ch^48);ch=getchar();}return x*f;}
#define Z(x) (x)*(x)
#define pb push_back
//mt19937 rand(time(0));
//mt19937_64 rand(time(0));
//srand(time(0));
#define N 5000010
//#define M
//#define mo
int n, m, i, j, k, T;
int sa[N], fa[N], ga[N], pa0[N], pa2[N];
int sb[N], fb[N], gb[N], pb0[N], pb2[N];
int ans, mx, p, pm;
char str[N];
void work(int *s, int *f, int *g, int *p0, int *p1) {
fill(s, s+n+1, 0);
fill(f, f+n+1, 0);
fill(g, g+n+1, 0);
fill(p0, p0+n+1, 0);
fill(p1, p1+n+1, 0);
for(i=1; i<=n; ++i) if(str[i]=='1') s[i]=1;
for(i=1; i<=n; ++i) s[i]+=s[i-1];
for(i=1, j=0; i<=n; ++i) if(str[i]=='0')
f[++j]=s[i], p0[j]=i;
for(i=n, j=0; i>=1; --i) if(str[i]=='2')
g[++j]=s[i], p1[j]=i;
// reverse(g+1, g+j+1);
// reverse(p1+1, p1+j+1);
}
struct Tree_Bin {
int cnt[N<<1], i;
void mem() {
for(i=0; i<(N<<1); ++i) cnt[i]=-1e9;
}
void add(int op, int x, int y) {
x*=op; x+=N;
while(x<(N<<1)) cnt[x]=max(cnt[x], y), x+=x&-x;
}
int que(int op, int x) {
x*=op;x+=N; int ans=-1e9;
while(x) ans=max(ans, cnt[x]), x-=x&-x;
return ans;
}
}Bin1, Bin2;
signed main()
{
freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
freopen("b.in", "r", stdin);
freopen("b.out", "w", stdout);
T=read();
while(T--) {
ans=0; Bin1.mem(); Bin2.mem();
scanf("%s", str+1); n=strlen(str+1);
work(sa, ga, fa, pa0, pa2);
scanf("%s", str+1); // only 1
work(sb, gb, fb, pb0, pb2);
// cout<<"sa : "; for(i=1; i<=n; ++i) printf("%d ", sa[i]); printf("\n");
// cout<<"sb : "; for(i=1; i<=n; ++i) printf("%d ", sb[i]); printf("\n");
// cout<<"pa0 : "; for(i=1; i<=n; ++i) printf("%d ", pa0[i]); printf("\n");
// cout<<"pa2 : "; for(i=1; i<=n; ++i) printf("%d ", pa2[i]); printf("\n");
ans=min(sa[n], sb[n]);
for(i=1, mx=m=0; i<=n; ++i) {
if(pa0[i] && pb0[i]) {
++mx;
ans=max(ans, mx+min(sa[n]-sa[pa0[mx]], sb[n]-sb[pb0[mx]])); //only 0 & 1
}
if(pa2[i] && pb2[i]) ++m;
}
//at most mx 0
reverse(fa+1, fa+m+1); reverse(pa2+1, pa2+m+1);
reverse(fb+1, fb+m+1); reverse(pb2+1, pb2+m+1);
// cout<<"pa2 : "; for(i=1; i<=n; ++i) printf("%d ", pa2[i]); printf("\n");
// cout<<"pb2 : "; for(i=1; i<=n; ++i) printf("%d ", pb2[i]); printf("\n");
pm=m;
ans=max(ans, mx); // only 0
for(i=1, m=0, j=1; i<=n; ++i)
if(pa2[i] && pb2[i]) {
++m;
while(j<=mx && pa0[j]<pa2[m] && pb0[j]<pb2[m]) {
Bin1.add(-1, ga[j]-gb[j], -ga[j]+j);
Bin2.add(1, ga[j]-gb[j], -gb[j]+j);
++j;
}
// printf("(%d[%d] %d)\n", m, pm-m+1, j-1) ;
ans=max(ans, pm-m+1+min(sa[pa2[m]], sb[pb2[m]])); // only 1 & 2
p=fa[m]-fb[m];
ans=max(ans, pm-m+1+fa[m]+Bin1.que(-1, p));
ans=max(ans, pm-m+1+fb[m]+Bin2.que(1, p));
}
ans=max(ans, m); //only 2
// printf("%d %d\n", mx, m);
printf("%d\n", ans);
}
return 0;
}