浏览器标题切换
浏览器标题切换end

寒假Day43:HDU1540 - Tunnel Warfare - 线段树+区间合并

题意

给出n个相邻的村庄,q个操作

D代表损坏一个村庄

R代表修复村庄

Q代表查询给定的村庄和多少个村庄相邻

思路

反正我还是没有想通为什么是用线段树这个算法来解决的。

AC代码

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<stack>
typedef long long ll;
using namespace std;
const int N=5e4+20;
#define inf 0x3f3f3f3f

int lsum[N<<2],rsum[N<<2],n;

void build(int L,int R,int i)
{
    lsum[i]=rsum[i]=R-L+1;
    if(L==R)
        return;
    int mid=(L+R)>>1;
    build(L,mid,i<<1);
    build(mid+1,R,i<<1|1);
}

//update(1,n,1,w,0);  flag:repair 0;restory 1
void update(int l,int r,int i,int x,int flag)
{
    if(l==r&&flag)
        lsum[i]=rsum[i]=0;
    if(l==r&&flag==0)
        lsum[i]=rsum[i]=1;
    if(l==r)
        return ;
    int mid=(l+r)>>1;
    if(x<=mid)
        update(l,mid,i<<1,x,flag);
    else
        update(mid+1,r,i<<1|1,x,flag);
    int len=r-l+1;
    lsum[i]=lsum[i<<1];
    rsum[i]=rsum[i<<1|1];
    if(lsum[i]==len-(len>>1))
        lsum[i]+=lsum[i<<1|1];
    if(rsum[i]==(len>>1))
        rsum[i]+=rsum[i<<1];
}

//query(1,n,1,x)
int query(int l,int r,int i,int x)
{
    if(l==r)
        return lsum[i];
    int ans=-inf,L=l+lsum[i]-1,R=r-rsum[i]+1;
    if(l<=x&&x<=L)//在左边
        ans=max(ans,lsum[i]);
    if(R<=x&&x<=r)//在右边
        ans=max(ans,rsum[i]);
    int mid=(l+r)>>1;
    if(mid-rsum[i<<1]+1<=x&&x<=mid+lsum[i<<1|1])
        ans=max(ans,lsum[i<<1|1]+rsum[i<<1]);
    if(ans!=-inf)
        return ans;
    if(x<=mid)
        return query(l,mid,i<<1,x);
    return query(mid+1,r,i<<1|1,x);
}

int main()
{
    int q,x;
    while(~scanf("%d %d",&n,&q))
    {
        build(1,n,1);
        stack<int>s;
        for(int i=1; i<=q; i++)
        {
            char ch[2];
            scanf("%s",ch);
            if(ch[0]=='D')//destory
            {
                scanf("%d",&x);
                s.push(x);
                update(1,n,1,x,1);
            }
            else if(ch[0]=='Q')//查询相连个数
            {
                scanf("%d",&x);
                int w=query(1,n,1,x);
                printf("%d\n",w);
            }
            else if(ch[0]=='R')//repair
            {
                int w=s.top();
                update(1,n,1,w,0);
                s.pop();
            }
        }
    }
    return 0;
}
posted @ 2020-03-06 20:32  抓水母的派大星  阅读(125)  评论(0编辑  收藏  举报