题意就不写了,小的input,就是个模拟。
大的可以把区间离散化,或者用线段树。
线段树每个区间记录一个low值,查询的时候,看当前节点和祖先节点low值最大的;更新时如果low变大了,记得更新祖先节点。
下面是代码:
#include <iostream>
#include <string.h>
#include <math.h>
#include <set>
#include <utility>
#define min(a,b) ((a) < (b) ? (a) : (b))
#define max(a,b) ((a) > (b) ? (a) : (b))
using namespace std;
const int N=101000001;
//const int N=100;
int minh;
int lp,rp;
struct node
{
int low;
//int l,r;
node *pl,*pr,*pa;
}*root,*last;
void del(node *&r)
{
if(r!=NULL)
{
del(r->pl);
del(r->pr);
delete r;
r=NULL;
}
}
void query(node* ro,int l,int r)
{
if(!ro)
{
int t=0;
ro=last;
while(ro)
{
t=max(t,ro->low);
ro=ro->pa;
}
minh=min(t,minh);
return ;
}
last=ro;
if(l==lp&&r==rp)
{
int t=0;
while(ro)
{
t=max(t,ro->low);
ro=ro->pa;
}
minh=min(t,minh);
return ;
}
int m=(lp+rp)/2;
if(r<=m)
{
int t=rp;
rp=(lp+rp)/2;
last=ro;
query(ro->pl,l,r);
rp=t;
}
else if(l>=m)
{
int t=lp;
lp=(lp+rp)/2;
last=ro;
query(ro->pr,l,r);
lp=t;
}
else
{
int t=rp;
rp=(lp+rp)/2;
last=ro;
query(ro->pl,l,m);
rp=t;
t=lp;
lp=(lp+rp)/2;
last=ro;
query(ro->pr,m,r);
lp=t;
}
}
void insert(node *&ro,int l,int r,int c)
{
if(!ro)
{
ro=new node();
ro->pl=NULL;
ro->pr=NULL;
ro->pa=last;
//ro->l=lp;
//ro->r=rp;
if(last)ro->low=last->low;
else ro->low=0;
}
if(l==lp&&r==rp)
{
if(ro->low<c)
{
ro->low=c;
node *tro=ro;
tro=tro->pa;
while(tro&&tro->pl&&tro->pr)
{
int tm=min(tro->pl->low,tro->pr->low);
if(tro->low>=tm)break;
tro->low=tm;
tro=tro->pa;
}
}
}
else
{
int m=(lp+rp)/2;
if(l<m)
{
int t=rp;
rp=(lp+rp)/2;
last=ro;
insert(ro->pl,l,min(r,m),c);
rp=t;
}
if(r>m)
{
int t=lp;
lp=(lp+rp)/2;
last=ro;
insert(ro->pr,max(l,m),r,c);
lp=t;
}
}
}
//void disp(node* r,int ma)
//{
// if(!r)return;
// if(r->pl==NULL&&r->pr==NULL)
// {
// printf("%d-%d %d\n",r->l,r->r,max(r->low,ma));
// }
// else
// {
// ma=max(ma,r->low);
// disp(r->pl,ma);
// disp(r->pr,ma);
// }
//}
struct tri
{
int d,n,w,e,s,dd,dp,ds;
tri()
{
scanf("%d%d%d%d%d%d%d%d",&d,&n,&w,&e,&s,&dd,&dp,&ds);
}
bool att(int ad)
{
if(ad<d)return 0;
if((ad-d)%dd==0)
{
int time=(ad-d)/dd;
if(time>=n)return 0;
minh=N;
query(root,w+time*dp,e+time*dp);
if(minh<s+time*ds)
{
//int pthis=0;
//while(tt[pthis]!=this)pthis++;
//printf("t %d d %d h %d ah %d %d-%d\n",pthis,ad,minh,s+time*ds,w+time*dp,e+time*dp);
return 1;
}
}
return 0;
}
void rep(int ad)
{
if(ad<d)return;
if((ad-d)%dd==0)
{
int time=(ad-d)/dd;
if(time>=n)return ;
insert(root,w+time*dp,e+time*dp,s+time*ds);
//disp(root,0);
}
}
}*tt[1005];
int main()
{
freopen("C-large-practice.in","r",stdin);
freopen("out.txt","w",stdout);
int cas;
int ki,i,j,nt,sum;
scanf("%d",&cas);
set<int>::iterator it;
lp=-N;
rp=N;
for(ki=1;ki<=cas;ki++)
{
root=last=NULL;
insert(root,-N,N,0);
sum=0;
set<int> ad;
printf("Case #%d: ",ki);
scanf("%d",&nt);
for(i=0;i<nt;i++)
{
tt[i]=new tri();
for(j=0;j<tt[i]->n;j++)
ad.insert(tt[i]->d+j*tt[i]->dd);
}
for(it=ad.begin();it!=ad.end();it++)
{
//printf("day:%d\n",*it);
for(i=0;i<nt;i++)
sum+=tt[i]->att(*it);
for(i=0;i<nt;i++)
tt[i]->rep(*it);
}
printf("%d\n",sum);
del(root);
}
return 0;
}