POI 2015
4384: [POI2015]Trzy wieże
claris的题解很详细
总结:
把区间不等关系写成前缀和形式----化成两点的不等
(x,y,z)三元组任意一维不等,则可以一维排序,一维树状数组,查询不同色的最大值、最小值
一开始感觉代码很乱,不知道自己的实现是否有错。
其实逻辑非常清楚,需要注意的只有变量名
还有为了防止下标<=0,加上n + 10,如果刚好+n会有=0的下标。
#include<bits/stdc++.h>
using namespace std;
#define rep(i,l,r) for(register int i = l ; i <= r ; i++)
#define repd(i,r,l) for(register int i = r ; i >= l ; i--)
#define rvc(i,S) for(register int i = 0 ; i < (int)S.size() ; i++)
#define rvcd(i,S) for(register int i = ((int)S.size()) - 1 ; i >= 0 ; i--)
#define fore(i,x)for (register int i = head[x] ; i ; i = e[i].next)
#define forup(i,l,r) for (register int i = l ; i <= r ; i += lowbit(i))
#define fordown(i,id) for (register int i = id ; i ; i -= lowbit(i))
#define pb push_back
#define prev prev_
#define stack stack_
#define mp make_pair
#define fi first
#define se second
#define lowbit(x) ((x)&(-(x)))
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
typedef pair<int,int> pr;
const int maxn = 1e6 + 20;
const int inf = 1e9;
int mx_id[2][maxn * 2],mn[2][maxn * 2],mn2[2][maxn * 2],mx[2][maxn * 2],mx2[2][maxn * 2],mn_id[2][maxn * 2];
int a[220];
int n,ans,cnt[maxn][3];
char ch[maxn];
struct node{
int a,b,c,id;
bool operator < (node x)const{
return a < x.a;
}
}dt[maxn];
inline int query(int t,int pos,int c,int id){
if ( pos <= 0 ) return 0;
int l = inf , r = 0;
fordown(i,pos){
if ( mx_id[t][i] == c ){
r = max(r,mx2[t][i]);
}
else r = max(r,mx[t][i]);
if ( mn_id[t][i] == c ){
l = min(l,mn2[t][i]);
}
else l = min(l,mn[t][i]);
}
// cout<<pos<<" "<<id<<" "<<l<<" "<<r<<endl;
return max(0,max(id - l,r - id));
}
inline void modify(int t,int pos,node x){
forup(i,pos,n * 2 + 10){
if ( mx[t][i] < x.id ){
if ( mx_id[t][i] != x.c ) mx2[t][i] = mx[t][i];
mx_id[t][i] = x.c , mx[t][i] = x.id;
}
else if ( mx2[t][i] < x.id && x.c != mx_id[t][i] ){
mx2[t][i] = x.id;
}
if ( mn[t][i] > x.id ){
if ( mn_id[t][i] != x.c ) mn2[t][i] = mn[t][i];
mn_id[t][i] = x.c , mn[t][i] = x.id;
}
else if ( mn2[t][i] > x.id && x.c != mn_id[t][i] ){
mn2[t][i] = x.id;
}
}
}
int main(){
scanf("%d%s",&n,ch + 1);
n = strlen(ch + 1);
a['B'] = 0 , a['C'] = 1 , a['S'] = 2;
dt[0] = (node){
0,0,0,0};
rep(i,1,n){
rep(k,0,2) cnt[i][k] = cnt[i - 1][k] + (a[ch[i]] == k);
int a = cnt[i][0] - cnt[i][1] , b = cnt[i][1] - cnt[i][2] , c = cnt[i][2] - cnt[i][0];
dt[i] = (node){
a,b,c,i};
}
rep(i,1,n * 2 + 10) rep(t,0,1) mn[t][i] = mn2[t][i] = inf;
sort(dt,dt + n + 1);
int last = 0;
// cout<<"dt : \n";
// rep(i,0,n) cout<<dt[i].a<<" "<<dt[i].b<<" "<<dt[i].c<<" "<<dt[i].id<<endl;
rep(i,0,n){
if ( i && dt[i].a != dt[i - 1].a ){
rep(j,last,i - 1){
modify(0,dt[j].b + n + 10,dt[j]);
modify(1,n - dt[j].b + 10,dt[j]);
}
last = i;
}
ans = max(ans,query(0,dt[i].b - 1 + n + 10,dt[i].c,dt[i].id));
ans = max(ans,query(1,n - dt[i].b - 1 + 10,dt[i].c,