您的位置:首页 > 其它

HDU - 1540Tunnel Warfare(线段树 单点更新 区间查询)

2017-06-10 23:45 417 查看
HDU - 1540  题目链接

这一题看上去是单点查询,其实是查询区间啦,查询x左边的靠右的区间和右边的靠左的区间的和。

今天看了一篇博客,感觉说的真的很好,自己动不动就去翻discuss和题解真的挺不好的。

刷题是为了什么呢,又不是为了题量,而是为了自己的思维能力。思维能力上不去,写的题再多有什么用啊。

在这里立下flag,以后除非卡成10天半个月或更久过不了题,再去翻题解,翻题解也别看代码,主要是思路。这个毛病可能一时半会改不过来,但是一定是要改的。

今天的效率也低的吓人。决定以后早点睡了。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define met(a,b) memset(a,b,sizeof(a))
const int maxn = 5e4+10;
int n,m;
int f[maxn],sta[maxn << 2];
int lm[maxn << 2], rm[maxn << 2];
int slen = 0;

void build(int l,int r,int id)
{
lm[id] = rm[id ] = r-l+1;
if(l == r) { return;}
int m = l+r>>1;
build(l,m,id<<1);
build(m+1,r,id<<1|1);
}
void up(int ti,int id,int way,int l,int r)
{
if(ti < l || ti > r) return;
if(ti == l && l == r){lm[id] = rm[id] = way; return;}

int m = l+r>>1;
if(ti <= m) up(ti,id<<1,way,l,m);
else up(ti,id<<1|1,way,m+1,r);

lm[id] = lm[id<<1]; rm[id] = rm[id<<1|1];
if(lm[id<<1] == (m-l+1)) lm[id] += lm[id<<1|1];
if(rm[id<<1|1] == (r-m)) rm[id] += rm[id<<1];

}

int q1(int ql,int qr,int id,int l,int r)
{
if(qr < l || ql > r) return 0;
if(l >= ql && r <= qr){return rm[id];}
int m = l+r>>1;
if(qr <= m) return q1(ql,qr,id<<1,l,m);
else if(ql > m) return q1(ql,qr,id<<1|1,m+1,r);
else
{
int ans = min(qr-m,q1(ql,qr,id<<1|1,m+1,r));
if(ans >= (qr-m)) ans += min(m-ql+1,q1(ql,qr,id<<1,l,m));
return ans;
}
}
int q(int ql,int qr,int id,int l,int r)
{
if(l >= ql && r <= qr){return lm[id];}
int m = l+r>>1;

if(qr <= m) return q(ql,qr,id<<1,l,m);
else if(ql > m) return q(ql,qr,id<<1|1,m+1,r);
else
{
int ans = min(m-ql+1,q(ql,qr,id<<1,l,m));
if(ans >= (m-ql+1)) ans += min(qr-m,q(ql,qr,id<<1|1,m+1,r));
return ans;
}
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
slen = 0;
met(f,0);
met(sta,0);
build(1,n,1);

for(int i = 0; i < m ; i++)
{
char s[3]; int a;
scanf("%s",s);
if(s[0] == 'R')
{
if(slen != 0)
{
int t = sta[--slen];
if(f[t]){ f[t] = 0; up(t,1,1,1,n); }
}
}
else
{
scanf("%d",&a);
if(s[0] == 'D'){sta[slen ++] = a; if(!f[a]){up(a,1,0,1,n); f[a] = 1;}}
else
{
if(!f[a])
{
int ans = 1,l = 0,r = 0;
if(a > 1) l += q1(1, a-1, 1, 1,n);
if(a < n) r += q(a+1, n, 1, 1, n);
printf("%d\n",ans+l+r);
}
else printf("0\n");
}
}
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: