【刷题计划】POI做题记录

这篇博客记录了作者参与POI竞赛的做题经历,包括2015年至2018年的题目,涉及树形DP、贪心、数论、线段树、竞赛图等多个知识点。作者在解题过程中遇到的陷阱和解决问题的方法,如化简问题为两点不等式、利用前缀和和树状数组、贪心策略、区间差分等。同时,作者也反思了自己的不足,如对某些题目的理解不深入,对算法的应用不够熟练,需要加强代码实现能力。
摘要由CSDN通过智能技术生成
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,
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值