题意:在抗日战争期间,地道战在华北平原得到广泛的实施,一般而言,村庄通过一些隧道在一条线上连接,除了两端剩下的每个村庄都有两个相连。
侵略者会频繁的对这些村庄进行扫荡,并且摧他们的地道,当然八路军会把这一些已经被摧毁的村庄修复的,会优先修复最近被破坏的村庄。
分析:被这道题折磨了一上午啊,不过也学到了很多,尤其是这种涉及左右区间的。
*********************************************************************
#include<stdio.h>
#include<algorithm>
#include<stack>
using namespace std;
const int maxn = 50005;
struct node
{//sum代表区间种最大的连续区间,lsum代表左端能到达的最右端的个数
int L, R, sum, lsum, rsum;
int Mid(){return (L+R)/2;}
int Len(){return (R-L+1);}
}a[maxn*4];
void Up(int r)
{
a[r].lsum = a[r<<1].lsum, a[r].rsum = a[r<<1|1].rsum;
if(a[r<<1].lsum == a[r<<1].Len())
a[r].lsum = a[r<<1].lsum + a[r<<1|1].lsum;
if(a[r<<1|1].rsum == a[r<<1|1].Len())
a[r].rsum = a[r<<1|1].rsum + a[r<<1].rsum;
a[r].sum = max(a[r].lsum, max(a[r].rsum, a[r<<1].rsum+a[r<<1|1].lsum));
}
void Build(int r, int L, int R)
{
a[r].L = L, a[r].R = R;
a[r].lsum = a[r].rsum = a[r].sum = a[r].Len();
if(L == R)return ;
Build(r<<1, L, a[r].Mid());
Build(r<<1|1, a[r].Mid()+1, R);
}
void Insert(int r, int k, int e)
{
if( a[r].L == a[r].R )
{
a[r].lsum = a[r].rsum = a[r].sum = e;
return ;
}
if(k <= a[r].Mid())
Insert(r<<1, k, e);
else
Insert(r<<1|1, k, e);
Up(r);
}
int Query(int r, int k)
{
if(a[r].sum == 0)return 0;
if(k < a[r].L+a[r].lsum)return a[r].lsum;//判断是否在左边
if(k > a[r].R-a[r].rsum)return a[r].rsum;//判断是否在右边
if(k > a[r<<1].R-a[r<<1].rsum && k < a[r<<1|1].L+a[r<<1|1].lsum)//判断是否在中间
return a[r<<1].rsum + a[r<<1|1].lsum;
if(k <= a[r].Mid())
return Query(r<<1, k);
else
return Query(r<<1|1, k);
}
int main()
{
int N, M;
while(scanf("%d%d", &N, &M) != EOF)
{
int x; char s[10];
stack<int> sta;
Build(1, 1, N);
while(M--)
{
scanf("%s", s);
if(s[0] == ‘D‘)
{
scanf("%d", &x);
Insert(1, x, 0);
sta.push(x);
}
else if(s[0] == ‘R‘ && sta.size())
{
Insert(1, sta.top(), 1);
sta.pop();
}
else if(s[0] == ‘Q‘)
{
scanf("%d", &x);
printf("%d\n", Query(1, x));
}
}
}
return 0;
}