题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=1540
题意:给一个村子求直接和间接和它连着的村子有多少个
思路:
待测代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <stack>
#include <map>
#include <cstring>
#include <climits>
#include <cmath>
#include <cctype>
const int inf = 0x3f3f3f3f;//1061109567
typedef long long LL;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int maxn = 50010;
int lsum[maxn<<2],rsum[maxn<<2],msum[maxn<<2];
int st[maxn];
using namespace std;
void pushup(int rt,int m)
{
lsum[rt] = lsum[rt<<1];
rsum[rt] = rsum[rt<<1|1];
if(lsum[rt] == (m>>1)) lsum[rt] += lsum[rt<<1|1];
if(rsum[rt] == m-(m>>1)) rsum[rt] += rsum[rt<<1];
msum[rt] = max(rsum[rt<<1]+lsum[rt<<1|1],max(msum[rt<<1],msum[rt<<1|1]));
}
void update(int v,int c,int l,int r,int rt)
{
if(l == r)
{
rsum[rt]=lsum[rt]=msum[rt]=c?0:1;
return;
}//每次更新的都是单独一个点,所以没有pushdown()
int m = (l+r)>>1;
if(v<=m) update(v,c,lson);
if(v>m) update(v,c,rson);
pushup(rt,r-l+1);
}
int query(int c,int l,int r,int rt)
{
if(l == r || msum[rt] == 0 || msum[rt] == r-l+1)
return msum[rt];
int m = (l+r)>>1;
if(c <= m)
{
if(c >= m-rsum[rt<<1]+1)
return query(c,lson)+query(m,rson);
else
return query(c,lson);
}
else
{
if(c <= m+lsum[rt<<1|1]-1)
return query(m,lson)+query(c,rson);
else
return query(c,rson);
}
}
void build(int l,int r,int rt)
{
lsum[rt]=rsum[rt]=msum[rt]=r-l+1;
if(l == r) return;
int m = (l+r)>>1;
build(lson);
build(rson);
}
int main()
{
int n,m,a;
char op[2];
while(scanf("%d%d",&n,&m) != EOF)
{
build(1,n,1);
int top=0;
while(m--)
{
scanf("%s",op);
if(op[0] == 'D')
{
scanf("%d",&a);
update(a,1,1,n,1);
st[top++] = a;
}
else if(op[0] == 'Q')
{
scanf("%d",&a);
int sum = query(a,1,n,1);
printf("%d\n",sum);
}
else if(op[0] == 'R')
{
int x =st[top--];
update(x,0,1,n,1);
}
}
}
return 0;
}