您的位置:首页 > 其它

HDU 1540 Tunnel Warfare 【线段树 + 思维】

2018-02-07 17:29 387 查看
传送门

// 题意: 初始1-n村庄全部相连, 然后有三种操作D x 表示摧毁x村, R 表示修复最近一个被摧毁的村, Q x 询问与x存间接或者直接相连的村有多少个,

首先询问很明显的就是最接近该询问村的的一段区间的maxx, 和minn值,可以用线段树来维护, 所以终点是找那段区间, 其实也比较好找,也就是二分找下即可.

AC Code

const int maxn = 5e4+5;
int cas=1;
struct node{
int tl, tr; ll mx, mi;
} tree[maxn*4];

void pushup(int id)
{
tree[id].mx = max(tree[id<<1].mx, tree[id<<1|1].mx);
tree[id].mi = min(tree[id<<1].mi, tree[id<<1|1].mi);
}

int vv;
void build(int id,int l,int r)
{
tree[id].tl = l; tree[id].tr = r;
if(l == r){
tree[id].mx = tree[id].mi = ++vv;
return ;
}
int mid = (l+r) >> 1;
build(id<<1, l, mid);
build(id<<1|1, mid+1, r);
pushup(id);
}

ll ansmx, ansmi;
void query(int id, int ql, int qr)
{
int l = tree[id].tl , r = tree[id].tr;
if(ql <= l && r <= qr) {
ansmx = max(ansmx, tree[id].mx);
ansmi = min(ansmi, tree[id].mi);
return ;
}
int mid = (l+r) >> 1 ;
if(ql <= mid) query(id<<1, ql, qr);
if(qr > mid) query(id<<1|1, ql, qr);
}
int a[maxn];
set<int>st; bool vis[maxn];
void solve()
{
int n, q;
while(~scanf("%d%d",&n, &q)) {
Fill(vis, false); st.clear();
vv = 0; int k = 0 ;
build(1, 1, n);
st.insert(0); st.insert(n+1);
while(q--){
string s; int w;
cin >> s;
if (s[0] == 'D') {
scanf("%d", &w);
a[++k] = w;
vis[w] = true;
st.insert(w);
}
else if (s[0] == 'R') {
st.erase(a[k]);
vis[a[k]] = false;
k--;
}
else {
scanf("%d", &w);
if (vis[w]) {
printf("0\n");
continue;
}
ansmx = 0, ansmi = inf;
auto it = st.upper_bound(w);
int r = *it; it--; int l = *it;
query(1, l+1, r-1);
printf("%d\n", ansmx - ansmi + 1);
}
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: