标签: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