您的位置:首页 > 其它

【线段树】 HDU 5289 Assignment

2015-07-21 19:03 495 查看
点击打开链接

对于第i个数,最多有 i个以i为R端的区间可以选

前面维护好一个L值 表示在L之前都不满足条件的位置

然后对于L-R二分

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
#include <vector>
typedef long long LL;
using namespace std;
const LL mod=1e9+7;
const int MAXN = 101000;//点数的最大值
const int MAXM = 160000;//边数的最大值
const int INF = 0x3f3f3f3f;
#define lson l,m, rt<<1
#define rson m+1,r,rt<<1|1
int read()
{
char ch=' ';
int ans=0;
while(ch<'0' || ch>'9')
ch=getchar();
while(ch<='9' && ch>='0')
{
ans=ans*10+ch-'0';
ch=getchar();
}
return ans;
}
int ans[MAXN<<2][2],x[MAXN];
void pushup(int rt)
{
ans[rt][0]=max(ans[rt<<1][0],ans[rt<<1|1][0]);
ans[rt][1]=min(ans[rt<<1][1],ans[rt<<1|1][1]);
}
void build(int l,int r,int rt)
{
if(l==r)
{
x[l]=read();
ans[rt][0]=ans[rt][1]=x[l];
return ;
}
int m=(l+r)>>1;
build(lson);
build(rson);
pushup(rt);
}
int querymax(int L,int R,int l,int r,int rt)
{
if(L<=l&&r<=R)
return ans[rt][0];
int m=(l+r)>>1;
int res=-INF;
if(L<=m) res=max(res,querymax(L,R,lson));
if(R>m) res=max(res,querymax(L,R,rson));
return res;
}
int querymin(int L,int R,int l,int r,int rt)
{
if(L<=l&&r<=R)
return ans[rt][1];
int m=(l+r)>>1;
int res=INF;
if(L<=m) res=min(res,querymin(L,R,lson));
if(R>m) res=min(res,querymin(L,R,rson));
return res;
}
int k,n;
int erfen(int L,int now,int orz)
{
int l=L,r=now,ans;
while(l<=r)
{
int m=(l+r)>>1;
if(querymax(m,now,1,n,1)-orz<k&&orz-querymin(m,now,1,n,1)<k)
{
r=m-1;
ans=m;
}
else l=m+1;
}
return ans;
}
int main()
{
int t;
// freopen("in.txt","r",stdin);
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&k);
build(1,n,1);
int L=1;
LL ans=0;
for(int i=1;i<=n;i++)
{
if (((querymax(L,i,1,n,1)-x[i])>=k)||(x[i]-querymin(L,i,1,n,1))>=k)
{
int xx=0;
xx=erfen(L,i,x[i]);
L=xx;
ans+=i-xx+1LL;
}
else
ans+=i-L+1;
}
printf("%I64d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  线段树