HDOJ 1540
题意:输入n,m表示n个村庄和m次操作。
后面m行,有3种操作:
- D x:第x个村庄被毁。
- Q x:指挥官询问第x个村庄与其直接或间接相关的村庄数量。
- R:最后毁坏的村庄被重建了。
方法一
分析:本来是线段树练习题,但是我第一眼看真的是STL裸题,用set就能解决。
#include <iostream>
#include <cmath>
#include <iomanip>
#include <cstring>
#include <vector>
#include <map>
#include <queue>
#include <stack>
#include <set>
#include <cstdio>
#include <algorithm>
#define INF 0x3f3f3f3f
#define PI acos(-1)
using namespace std;
typedef long long ll;
typedef pair<ll, ll> P;
const int mod=1e9+7;
const int maxn=5e4+10;
ll n,m;
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
while (cin>>n>>m) {
char tag;
set <ll> s;
stack <ll> k;
set <ll> :: iterator it;
ll last;
while (m--) {
cin>>tag;
if (tag=='D') {
cin>>last;
s.insert(last);
k.push(last);
}
else if (tag=='Q') {
cin>>last;
if (s.count(last)) {
cout<<"0"<<endl;
continue;
}
it=s.upper_bound(last);
ll t=*it;
//cout<<t<<endl;
if (it!=s.end()) {
if (it!=s.begin()){
it--;
cout<<t-*it-1<<endl;
}
else {
cout<<t-1<<endl;
}
}
else {
if (s.empty()) cout<<n<<endl;
else {
it=s.end();
it--;
cout<<n-*it<<endl;
}
}
}
else {
last=k.top();
k.pop();
s.erase(last);
}
}
}
return 0;
}
方法二
分析:线段树维护最大连续子段和
#include <iostream>
#include <cmath>
#include <iomanip>
#include <cstring>
#include <vector>
#include <map>
#include <queue>
#include <stack>
#include <set>
#include <cstdio>
#include <algorithm>
#define INF 0x3f3f3f3f
#define PI acos(-1)
using namespace std;
typedef long long ll;
typedef pair<ll, ll> P;
const int mod=1e9+7;
const int maxn=5e4+10;
struct Node {
ll ms,ls,rs;
} tree[maxn<<2];
ll n,m;
void push_up(ll p, ll l, ll r){
ll lson=p<<1;
ll rson=(p<<1)|1;
ll m=(l+r)>>1;
tree[p].ls=tree[lson].ls;
tree[p].rs=tree[rson].rs;
//左子树 ls = 区间,则加上 右子树 ls
if (tree[lson].ls==m-l+1) tree[p].ls+=tree[rson].ls;
//右子树 rs = 区间,则加上 左子树 rs
if (tree[rson].rs==r-m) tree[p].rs+=tree[lson].rs;
tree[p].ms=max(max(tree[lson].ms,tree[rson].ms),tree[lson].rs+tree[rson].ls);
}
void build(ll p, ll l, ll r){
if (l==r){
tree[p].ls=tree[p].rs=tree[p].ms=1;
return;
}
ll m=(l+r)>>1;
build(p<<1,l,m),build((p<<1)|1,m+1,r);
push_up(p,l,r);
}
void update(ll p, ll x, ll z, ll l, ll r) {
if (l==r) {
tree[p].ls=tree[p].rs=tree[p].ms=z;
return;
}
ll m=(l+r)>>1;
if (x<=m) update(p<<1,x,z,l,m);
else update((p<<1)|1,x,z,m+1,r);
push_up(p,l,r);
}
ll query(ll p, ll x, ll s, ll t) {
if (s==t || tree[p].ms==0) return tree[p].ms;
ll m=(s+t)>>1;
if (x<=m){
// x 在左子树 rs 的区间中, 则与右子树 ls 相连
if (m-x+1<=tree[p<<1].rs)
return tree[p<<1].rs+tree[(p<<1)|1].ls;
else return query(p<<1,x,s,m);
//如果x不在这个区间,说明x还在左边,继续查询
}
else {
// x 在右子树 ls 的区间中,则与左子树 rs 相连
if (x-m<=tree[(p<<1)|1].ls)
return tree[p<<1].rs+tree[(p<<1)|1].ls;
else return query((p<<1)|1,x,m+1,t);
//如果x不在这个区间,说明x还在右边,继续查询
}
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
while (cin>>n>>m) {
char tag;
build(1,1,n);
ll last;
stack <ll> k;
while (m--) {
cin>>tag;
if (tag=='D') {
cin>>last;
k.push(last);
update(1,last,0,1,n);
}
else if (tag=='Q') {
cin>>last;
cout<<query(1,last,1,n)<<endl;
}
else {
last=k.top();
k.pop();
update(1,last,1,1,n);
}
}
}
return 0;
}