HDU - 1540 Tunnel Warfare(暴力分块)

传送门
题目大意:给一个01序列.支持查询i位置最大的连续1子串的长度.
可以二分+树状数组.不过不用那么麻烦,直接暴力分块就好了.
只需要维护一个信息.块上是否只有1.不是的话就暴力找到第一个0.是的话就找下一个块.这样子复杂度就是O(nsqrt(n))的.
HDU 和 POJ上的老题都会有很多说的不清不楚的点.一个点可能多次被摧毁,但修复了之后就不用再次修复了,还有多组数据输入.
代码(虽然代码有点长,但思考难度几乎为0)

#pragma GCC optimize(3)
#define LL long long
#define pq priority_queue
#define ULL unsigned long long
#define pb push_back
#define mem(a,x) memset(a,x,sizeof a)
#define pii pair<int,int>
#define fir(i,a,b) for(int i=a;i<=b;++i)
#define afir(i,a,b) for(int i=a;i>=b;--i)
#define ft first
#define vi vector<int>
#define sd second
#define ALL(a) a.begin(),a.end()
#include <string.h>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstdio>
#include <queue>
#include <cmath>

using namespace std;
const int N = 5e4+10;
inline LL read(){
	LL x = 0,f=1;char ch = getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
void write(LL k) {
    if (k < 0)
        putchar('-'), k = -k;
    if (k >= 10)
        write(k / 10);
    putchar(k % 10 + '0');
}
int n,m,blo,num,a[N],L[N],R[N],pos[N],v[N];
void build(){
	blo = sqrt(n);
	num = n/blo;
	fir(i,1,num){
		L[i] = (i-1)*blo+1;
		R[i] = i*blo;
	}
	if(n % blo){
		num++;
		L[num] = R[num-1]+1;
		R[num] = n;
	}
	fir(i,1,num){
		v[i] = 1;
		fir(j,L[i],R[i]){
			a[j] = 1;
			pos[j] = i;
		}
	}
}
int s[N],idx=0;
void change(int l,int x){
	int p = pos[l];
	a[l] = x;
	if(x){
		fir(i,L[p],R[p]){
			if(a[i] != 1){
				v[p] = 0;
				return;
			}
		}
		v[p] = 1;
	}
	else v[p] = 0;
}
int query(int l){
	int res = 0;
	int p = pos[l];
	bool f = 0;
	if(a[l]){
	afir(i,l,L[p]){
		if(!a[i]){
			f = 1;
			break;
		}
		res++;
	}
	int left = p;
	if(!f){
		left--;
		while(left && v[left]){
			res += R[left] - L[left] + 1;
			left--;
		}
		if(left){
			afir(i,R[left],L[left]){
				if(!a[i]) break;
				res++;
			}
		}
	}
	int right = p;
	f = 0;
	if(l == R[p] && !a[l]) f = 1;
	fir(i,l+1,R[p]){
		if(!a[i]){
			f = 1;
			break;
		}
		res++;
	}
	if(!f){
		right++;
		while(right <= num && v[right]){
			res += R[right] - L[right] + 1;
			right++;
		}
		if(right <= num){
			fir(i,L[right],R[right]){
				if(!a[i]) break;
				res++;
			}
		}
	}
	}
	return res;
}
int main(){
	ios::sync_with_stdio(false);
	while(cin >> n >> m){
		build();
		idx = 0;
		while(m--){
			char op;
			int x;
			cin >> op;
			if(op == 'R'){
				while(idx && a[s[idx]]) idx--;
				if(!idx) continue;
				change(s[idx],1);
				idx--;
			}
			else{
				cin >> x;
				if(op == 'Q'){
					write(query(x));
					puts("");
				}
				else{
					change(x,0);
					s[++idx] = x;
				}
			}
			//fir(i,1,n) cout << a[i] << " ";
			//puts("");
		}
	}
	
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值