区间合并 连续性问题 查询与第x个村相连的村子有多少个
2015-10-11 18:04
281 查看
题目链接 hdu1540 Tunnel Warfare
题目大意:有N个村子排成一条直线,每个村子都连接了它的左右两个村子(除了最左边和最右边的外),有3种操作,(1)"D x",表示将第x个村子摧毁。(2)"Q x",表示查询与第x个村子直接和间接相连的村子有多少个。(3)"R",表示将最早摧毁的村子复原。
解题思路:O(-1)
#include <cstdio>
#include <vector>
#include <map>
#include <iostream>
using namespace std;
#define lz 2*u,l,mid
#define rz 2*u+1,mid+1,r
const int maxn=50005;
int flag[4*maxn];
int stack[maxn];
int top;
struct segment
{
int lm;
int rm;
int sm;
} tree[4*maxn];
void push_up(int u, int l, int r)
{
int mid= (l+r)>>1;
tree[u].lm= tree[u*2].lm;
tree[u].rm= tree[u*2+1].rm;
tree[u].sm= max( tree[u*2].sm, tree[u*2+1].sm );
if( tree[u*2].lm == mid-l+1 ) tree[u].lm += tree[u*2+1].lm;
if( tree[u*2+1].rm == r-mid ) tree[u].rm += tree[u*2].rm;
int t= tree[u*2].rm + tree[u*2+1].lm;
if( t > tree[u].sm ) tree[u].sm= t;
}
void build(int u, int l, int r)
{
flag[u]=-1;
if(l==r)
{
tree[u].lm= tree[u].rm= tree[u].sm= 1;
return;
}
int mid= (l+r)>>1;
build(lz);
build(rz);
push_up(u, l, r);
}
void Update(int u, int l, int r, int pos, int c)
{
if(l==r)
{
tree[u].lm=tree[u].rm=tree[u].sm=c;
return ;
}
int mid=(l+r)>>1;
if(pos<=mid) Update(lz,pos,c);
else Update(rz,pos,c);
push_up(u,l,r);
}
int Query(int u, int l, int r, int p)
{
if(tree[u].sm==r-l+1) return tree[u].sm;
if(l==r) return 0;
int mid=(l+r)>>1;
if(mid-tree[2*u].rm+1<=p&&p<=mid+tree[2*u+1].lm)
return tree[2*u].rm+tree[2*u+1].lm;
else if(p<=mid) return Query(lz,p);
else return Query(rz,p);
}
int main()
{
int n, m, op;
while(cin >> n >> m)
{
map<int,int>mp;
top=0;
build(1,1,n);
while(m--)
{
char ch[5];
scanf("%s",ch);
if(ch[0]=='D')
{
scanf("%d",&op);
Update(1,1,n,op,0);
stack[++top]=op;
}
else if(ch[0]=='R')
{
if(top) Update(1,1,n,stack[top--],1);
}
else
{
scanf("%d",&op);
int ans=Query(1,1,n,op);
printf("%d\n",ans);
}
}
}
return 0;
}
题目大意:有N个村子排成一条直线,每个村子都连接了它的左右两个村子(除了最左边和最右边的外),有3种操作,(1)"D x",表示将第x个村子摧毁。(2)"Q x",表示查询与第x个村子直接和间接相连的村子有多少个。(3)"R",表示将最早摧毁的村子复原。
解题思路:O(-1)
#include <cstdio>
#include <vector>
#include <map>
#include <iostream>
using namespace std;
#define lz 2*u,l,mid
#define rz 2*u+1,mid+1,r
const int maxn=50005;
int flag[4*maxn];
int stack[maxn];
int top;
struct segment
{
int lm;
int rm;
int sm;
} tree[4*maxn];
void push_up(int u, int l, int r)
{
int mid= (l+r)>>1;
tree[u].lm= tree[u*2].lm;
tree[u].rm= tree[u*2+1].rm;
tree[u].sm= max( tree[u*2].sm, tree[u*2+1].sm );
if( tree[u*2].lm == mid-l+1 ) tree[u].lm += tree[u*2+1].lm;
if( tree[u*2+1].rm == r-mid ) tree[u].rm += tree[u*2].rm;
int t= tree[u*2].rm + tree[u*2+1].lm;
if( t > tree[u].sm ) tree[u].sm= t;
}
void build(int u, int l, int r)
{
flag[u]=-1;
if(l==r)
{
tree[u].lm= tree[u].rm= tree[u].sm= 1;
return;
}
int mid= (l+r)>>1;
build(lz);
build(rz);
push_up(u, l, r);
}
void Update(int u, int l, int r, int pos, int c)
{
if(l==r)
{
tree[u].lm=tree[u].rm=tree[u].sm=c;
return ;
}
int mid=(l+r)>>1;
if(pos<=mid) Update(lz,pos,c);
else Update(rz,pos,c);
push_up(u,l,r);
}
int Query(int u, int l, int r, int p)
{
if(tree[u].sm==r-l+1) return tree[u].sm;
if(l==r) return 0;
int mid=(l+r)>>1;
if(mid-tree[2*u].rm+1<=p&&p<=mid+tree[2*u+1].lm)
return tree[2*u].rm+tree[2*u+1].lm;
else if(p<=mid) return Query(lz,p);
else return Query(rz,p);
}
int main()
{
int n, m, op;
while(cin >> n >> m)
{
map<int,int>mp;
top=0;
build(1,1,n);
while(m--)
{
char ch[5];
scanf("%s",ch);
if(ch[0]=='D')
{
scanf("%d",&op);
Update(1,1,n,op,0);
stack[++top]=op;
}
else if(ch[0]=='R')
{
if(top) Update(1,1,n,stack[top--],1);
}
else
{
scanf("%d",&op);
int ans=Query(1,1,n,op);
printf("%d\n",ans);
}
}
}
return 0;
}
相关文章推荐
- android 取消标题栏出错,程序崩溃的问题
- 循环移动
- 基于tcp的socket编程。
- ZOJ 5638——Prime Query——————【线段树区间更新,区间查询,单点更新】
- Android深入浅出之Binder机制
- c#创建、安装、卸载、调试windows服务的简单事例
- 抽象类和接口
- 【Python】Learn Python the hard way, ex24 函数综合练习
- 学习opencv(一)——扒一扒opencv中的一些基本数据类型
- 后缀数组
- 【转】Java学习之Iterator(迭代器)的一般用法 (转)
- 第五周信息安全系统设计基础学习总结 20135306 黄韧
- Ubuntu下的UNITY和GNOME界面
- 区间合并 内纯释放问题 hdu2871 Memory control
- 第20章 数据库函数库
- iOS中引用第三方类库的方法总结
- 【经典算法】:英文文章统计字符频率
- [机器学习] Adaboost算法流程及原理推导
- 关于搭建Tomcat服务器
- 校园招聘