Trees
Accepts: 156
Submissions: 533
Time Limit: 2000/1000 MS (Java/Others)
Memory Limit: 65536/65536 K (Java/Others)
问题描述
今天CodeFamer去坎树。有 N 棵树排成一排。他们被从 1 到 N 标号。第 i 号树的高度为 h i 。两棵未被坎掉的树编号分别为 x,y
当且仅当他们满足如下条件中一条时,他们是属于同一个块的: 1) x+1=y 或 y+1=x; 2) 存在一个棵未被坎掉的树,编号为 z , x 和 z 在同一个块并且 y 和 z 也在同一个块。 现在CodeFamer想要坎掉一些高度不大于某个值的树,坎掉之后会形成多少个块呢?
输入描述
多组测试数据(大概 15 组) 对于每一组数据,第一行包含两个整数 N 和 Q ,以一个空格分开, N 表示有 N 棵树, Q 表示有 Q 个查询。 在接下来的 N 行中,会出现 h[1],h[2],h[3],…,h[N] ,表示 N 棵树的高度。 在接下来的 Q 行中,会出现 q[1],q[2],q[3],…,q[Q] 表示CodeFamerr查询。 请处理到文件末尾。 [参数约定] 1≤N,Q≤50000 0≤h[i]≤1000000000(10 9 ) 0≤q[i]≤1000000000(10 9 )
输出描述
对于每一个q[i],输出CodeFamer坎掉高度不大于q[i]的树之后有多少个块。
输入样例
3 2 5 2 3 6 2
输出样例
0 2
Hint
在这个样例中,有3棵树,他们的高度依次是5 2 3。 对于6这个查询,如果CodeFamer坎掉高度不大于6的树,那么剩下的树高度形状是-1 -1 -1(-1表示那个树被坎掉了)。这样就有0个块。 对于2这个查询,如果CodeFamer坎掉高度不大于2的树,那么剩下的树高度形状是5 -1 3(-1表示那个树被坎掉了)。这样就有2个块。
离线处理询问
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<functional>
#include<iostream>
#include<cmath>
#include<cctype>
#include<ctime>
#include<vector>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=pre[x];p;p=next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=next[p])
#define Lson (x<<1)
#define Rson ((x<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (100000007)
#define MAXN (50000+10)
#define fi first
#define se second
typedef long long ll;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return (a-b+(a-b)/F*F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
int n,Q;
ll h[MAXN],q[MAXN];
bool b[MAXN];
pair<ll,int> ask[MAXN],work[MAXN];
int sum[MAXN];
int main()
{
// freopen("c.in","r",stdin);
while(scanf("%d%d",&n,&Q)==2)
{
MEM(h) MEM(q) MEM(b)
For(i,n)
{
scanf("%d",&h[i]);
work[i]=make_pair(h[i],i);
b[i]=1;
}
sort(work+1,work+1+n);
For(i,Q)
{
scanf("%d",&q[i]);
ask[i]=make_pair(q[i],i);
}
sort(ask+1,ask+1+Q);
int i=1,j=1,ans=1;
while (j<=Q)
{
if (i<=n&&work[i].fi<=ask[j].fi) //cut tree
{
int now=work[i].se;
b[now]=0;
ans+=b[now-1]+b[now+1]-1;
i++;
}
else // calc ans
{
int now=ask[j].se;
sum[now]=ans;
j++;
}
}
For(i,Q) printf("%d\n",sum[i]);
}
return 0;
}