标签:des style blog http os io 2014 for

4 3 5 8 1 2 6 2 3 3 2 4 7 1 5 2 2 2 1 5 3 1 1 10 4 2 3 7
11 10 18
思路:按到start line的距离建树,把线段转换成两个点,逐一插入,插入的时候相同的节点可以共享(如pre的左子树跟x的左子树相同则直接让x的左子树的指针只想pre的左子树即可)。详见代码。
#include <cstdio>
#include <algorithm>
#define LL long long
using namespace std;
struct P{
int pos,val,flag;
bool operator<(const struct P &p) const
{
if(pos==p.pos)
{
if(val==p.val) return flag<p.flag;
else return val<p.val;
}
else return pos<p.pos;
}
}pt[4000000],ts;//把每条线段转换成两个点,flag=1代表起点,falg=-1代表终点
int ls[4000000],rs[4000000],T[200005],vv[100000],cnum[4000000],nodenum;//ls指向左子树,rs指向右子树,T[i]为树i的根,cnum记录当前节点插入的值的个数
LL sum[4000000];
void insert(int s,int e,int val,int flag,int pre,int &x)//在pre的基础上插入一个点,如果插左边则右子树与pre的右子树相同,直接让x的右子树指向
{ //pre的右子树,再新建左子树
x=++nodenum;
ls[x]=ls[pre];//先让x的左右子树都指向pre的左右子树
rs[x]=rs[pre];
sum[x]=sum[pre]+flag*vv[val];//求和
cnum[x]=cnum[pre]+flag;//记录该节点插入的值的个数
if(s!=e)
{
int mid=(s+e)>>1;
if(val<=mid) insert(s,mid,val,flag,ls[pre],ls[x]);//插左边就在pre左子树的基础上建x的左子树
else insert(mid+1,e,val,flag,rs[pre],rs[x]);//右边同理
}
}
LL query(int s,int e,int k,int idx)
{
if(s==e) return k*vv[s];//如果到了叶子节点返回k*距离
int mid=(s+e)>>1;
if(cnum[ls[idx]]>k) return query(s,mid,k,ls[idx]);//如果插入左子树的值的个数大于k就在左子树找
else if(cnum[ls[idx]]==k) return sum[ls[idx]];//如果插入左子树的值的个数等于k就直接返回左子树的sum
else return sum[ls[idx]]+query(mid+1,e,k-cnum[ls[idx]],rs[idx]);//如果插入左子树的值的个数小于k就在右子树找(k-左子树插入的个数)
}
int main()
{
int n,m,x,p,i,l,r,val,cnt,t;
LL pre,pos,a,b,c,k,ans;
while(~scanf("%d%d%d%d",&n,&m,&x,&p))
{
for(i=0;i<n;i++)
{
scanf("%d%d%d",&l,&r,&val);
vv[i]=val;
pt[i*2].pos=l;
pt[i*2].val=val;
pt[i*2].flag=1;
pt[i*2+1].pos=r+1;
pt[i*2+1].val=val;
pt[i*2+1].flag=-1;
}
sort(vv,vv+n);
cnt=unique(vv,vv+n)-vv;//把距离重复的去掉
int lxd=0;//当前已经建好的树的数量
for(i=0;i<n*2;i++) pt[i].val=lower_bound(vv,vv+cnt,pt[i].val)-vv;//把距离转化成在vv数组里面的下标
sort(pt,pt+n*2);//按(pos,val,flag)升序排序
T[0]=ls[0]=rs[0]=sum[0]=cnum[0]=nodenum=0;
pre=1;
for(i=0;i<m;i++)
{
scanf("%I64d%I64d%I64d%I64d",&pos,&a,&b,&c);
k=(a*pre+b)%c;
ts.pos=pos;
ts.val=cnt;
t=upper_bound(pt,pt+n*2,ts)-pt;//找到pos对应的第t棵树
while(lxd<t)//如果第t棵树还没建好就建树一直到建好第t棵树为止
{
insert(1,cnt,pt[lxd].val,pt[lxd].flag,T[lxd],T[lxd+1]);//在第lxd棵树的基础上建第lxd+1棵树
lxd++;
}
ans=query(1,cnt,k,T[t]);//在第t棵树上查询
if(pre>p) ans*=2;
pre=ans;
printf("%I64d\n",ans);
}
}
}
HDU-4866-Shooting(函数式线段树),布布扣,bubuko.com
标签:des style blog http os io 2014 for
原文地址:http://blog.csdn.net/faithdmc/article/details/38143049