您的位置:首页 > 其它

CodeFoces 500E - New Year Domino

2015-01-11 10:03 218 查看
首先将所有的牌子放倒,那么花费就是牌子L和牌子R之间的空隙长度。

有一种特殊情况,存在牌子P(p < L)特别长,以至于影响了L,R之间的空隙长度。

所以我只想到了一种离线算法。

cov[i] 记录覆盖牌子i的编号。

dis[i] 记录推到牌子i所能到达的最远距离。

cost[i]记录L= i,R = n 时的最小花费。

首先预处理出dis[i],cost[i]。

然后将询问按L排序,然后从右到左枚举牌子。

枚举时不断更新cov[i],然后分类讨论得到答案。

弱用了三棵线段树才水过去,应该存在更简洁的方法。

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <queue>
#include <cmath>
#include <stack>
#include <map>
#include <ctime>
#include <iomanip>

#pragma comment(linker,"/STACK:1024000000");
#define EPS (1e-6)
#define LL long long
#define ULL unsigned long long
#define _LL __int64
#define INF 0x3f3f3f3f
#define Mod 1000000007
#define mod 1000000007

/** I/O Accelerator Interface .. **/
#define g (c=getchar())
#define d isdigit(g)
#define p x=x*10+c-'0'
#define n x=x*10+'0'-c
#define pp l/=10,p
#define nn l/=10,n
template<class T> inline T& RD(T &x)
{
char c;
while(!d);
x=c-'0';
while(d)p;
return x;
}
template<class T> inline T& RDD(T &x)
{
char c;
while(g,c!='-'&&!isdigit(c));
if (c=='-')
{
x='0'-g;
while(d)n;
}
else
{
x=c-'0';
while(d)p;
}
return x;
}
inline double& RF(double &x) //scanf("%lf", &x);
{
char c;
while(g,c!='-'&&c!='.'&&!isdigit(c));
if(c=='-')if(g=='.')
{
x=0;
double l=1;
while(d)nn;
x*=l;
}
else
{
x='0'-c;
while(d)n;
if(c=='.')
{
double l=1;
while(d)nn;
x*=l;
}
}
else if(c=='.')
{
x=0;
double l=1;
while(d)pp;
x*=l;
}
else
{
x=c-'0';
while(d)p;
if(c=='.')
{
double l=1;
while(d)pp;
x*=l;
}
}
return x;
}
#undef nn
#undef pp
#undef n
#undef p
#undef d
#undef g
using namespace std;

struct N
{
int l,p;
}st[200010];

int far[200010];

int Max[800100];

int dis[200010];

int Val[800100];

LL cost[200100];

int Init(int site,int l,int r)
{
if(l == r)
return Val[site] = st[l].l+st[l].p;

int mid = (l+r)>>1;

return Val[site] = max(Init(site<<1,l,mid),Init(site<<1|1,mid+1,r));
}

void Update(int site,int l,int r,int x,int d)
{
if(l == r)
{
Max[site] = max(Max[site],d);
return ;
}

int mid = (l+r)>>1;

if(x <= mid)
Update(site<<1,l,mid,x,d);
else
Update(site<<1|1,mid+1,r,x,d);
Max[site] = max(Max[site<<1],Max[site<<1|1]);
}

int Query(int site,int L,int R,int l,int r)
{
if(L == l && R == r)
return Max[site];

int mid = (L+R)>>1;

if(r <= mid)
return Query(site<<1,L,mid,l,r);
if(mid < l)
return Query(site<<1|1,mid+1,R,l,r);

return max(Query(site<<1,L,mid,l,mid),Query(site<<1|1,mid+1,R,mid+1,r));
}

int Query1(int site,int L,int R,int l,int r)
{
if(L == l && R == r)
return Val[site];

int mid = (L+R)>>1;

if(r <= mid)
return Query1(site<<1,L,mid,l,r);
if(mid < l)
return Query1(site<<1|1,mid+1,R,l,r);

return max(Query1(site<<1,L,mid,l,mid),Query1(site<<1|1,mid+1,R,mid+1,r));
}

int BS(LL x,int s,int e)
{
int mid , site = 0;

while(s <= e)
{
mid = (s+e)>>1;

if(st[mid].p <= x)
s = mid+1,site = mid;
else
e = mid-1;
}

return site;
}

void Cal(int x,int n)
{
int site = BS(st[x].l+st[x].p,x,n);

if(site == x)
far[x] = x;
else if(site == n)
far[x] = n;
else
far[x] = Query(1,1,n,x,site);

Update(1,1,n,x,far[x]);
}

int FindSite(int x,int l,int r)
{
int mid,site = r;

while(l <= r)
{
mid = (l+r)>>1;
if(far[mid] == x)
site = min(site,mid);
if(far[mid] < x)
l = mid+1;
else
r = mid-1;
}
return site;
}

struct Qu
{
int l,r,site;
LL anw;
}qu[200010];

bool cmp1(Qu q1,Qu q2)
{
return q1.l < q2.l;
}

bool cmp2(Qu q1,Qu q2)
{
return q1.site < q2.site;
}

struct Co
{
int id;
bool mark;
}cov[800100];

void InitCo(int site,int l,int r)
{
if(l == r)
{
cov[site].id = l,cov[site].mark = true;
return ;
}
int mid =(l+r)>>1;

InitCo(site<<1,l,mid);
InitCo(site<<1|1,mid+1,r);

if(cov[site<<1].id == cov[site<<1|1].id && cov[site<<1].id != -1)
cov[site].mark = true,cov[site].id = cov[site<<1].id;
else
cov[site].mark = false,cov[site].id = -1;
}

void UpdateCo(int site,int L,int R,int l,int r,int id)
{
if(L == l && R == r)
{
cov[site].mark = true;
cov[site].id = id;
return ;
}

int mid = (L+R)>>1;

if(cov[site].mark == true)
{
cov[site<<1] = cov[site];
cov[site<<1|1] = cov[site];

cov[site].mark = false;
cov[site].id = -1;
}

if(r <= mid)
UpdateCo(site<<1,L,mid,l,r,id);
else if(mid < l)
UpdateCo(site<<1|1,mid+1,R,l,r,id);
else
{
UpdateCo(site<<1,L,mid,l,mid,id);
UpdateCo(site<<1|1,mid+1,R,mid+1,r,id);
}

if(cov[site<<1].id == cov[site<<1|1].id && cov[site<<1].id != -1)
cov[site].mark = true,cov[site].id = cov[site<<1].id;
else
cov[site].mark = false,cov[site].id = -1;
}

int QueryCo(int site,int L,int R,int x)
{
if(cov[site].mark )
return cov[site].id;

int mid = (L+R)>>1;

if(x <= mid)
return QueryCo(site<<1,L,mid,x);
else
return QueryCo(site<<1|1,mid+1,R,x);
}

int main()
{
int n,i,j,q;

scanf("%d",&n);

for(i = 1;i <= n; ++i)
scanf("%d %d",&st[i].p,&st[i].l);

memset(Max,0,sizeof(Max));

Update(1,1,n,n,n);

for(far
= n,i = n-1; i >= 1; --i)
Cal(i,n);

Init(1,1,n);

for(i = 1;i <= n; ++i)
dis[i] = Query1(1,1,n,i,far[i]);

for(cost
= 0,i = n-1;i >= 1; --i)
{
if(far[i] == n)
cost[i] = 0;
else
cost[i] = cost[far[i]+1] + st[far[i]+1].p - dis[i];
}

scanf("%d",&q);

int site;

for(i = 1;i <= q; ++i)
{
scanf("%d %d",&qu[i].l,&qu[i].r);
qu[i].site = i;
}

sort(qu+1,qu+q+1,cmp1);

InitCo(1,1,n);

for(j = q,i = n;i >= 1; --i)
{
UpdateCo(1,1,n,i,far[i],i);

while(j >= 1 && qu[j].l == i)
{
if(far[i] >= qu[j].r)
qu[j].anw = 0;
else
{
site = QueryCo(1,1,n,qu[j].r);
if(far[i] >= site)
qu[j].anw = 0;
else
qu[j].anw = cost[i] - cost[site];
}
j--;
}
}

sort(qu+1,qu+q+1,cmp2);

for(i = 1;i <= q; ++i)
{
printf("%I64d\n",qu[i].anw);
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: