HDU-4866-Shooting(函数式线段树)
the position of [Li, Ri] , the distance from the starting line is Di(1<=i<=N). Shooting a target can get the bonus points equal to the distance to the starting line. After each shooting targets still exist. Additional, if the previous bonus points is more
than P, then as a reward for the shooting present bonus points doubled(and then check the next one). Player wants to know the bonus points he got in each shot.
The first line has two integers, N, M, X, P(1<=N, M ,X<=100000, P<=1000000000), N represents the total number of target shooting, M represents the number of shooting.
The next N lines of three integers L, R, D (1<=L<=R<=X, 1<=D<=10000000), occupy the position of [L, R] and the distance from the starting line is D.
The next M lines, each line contains four integers x, a, b, c (1<=x<=X, 0<=a,b<=N, 1<=c<=10000000), and K = ( a * Pre + b ) % c. Pre is the bonus point of previous shooting , and for the first shooting Pre=1. It denotes standing in the position x and the player
can shoot the nearest K targets.
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(函数式线段树)的更多相关文章
- HDU 4866 Shooting(持久化线段树)
view code//第二道持久化线段树,照着别人的代码慢慢敲,还是有点不理解 #include <iostream> #include <cstdio> #include & ...
- HDU 4866 Shooting (主席树)
题目链接 HDU 4866 题意 给定$n$条线段.每条线段平行$x$轴,离x轴的距离为$D$,覆盖的坐标范围为$[L, R]$. 现在有$m$次射击行动,每一次的射击行动可以描述为在横坐标$ ...
- HDU 4866 Shooting 扫描线 + 主席树
题意: 在二维平面的第一象限有\(n(1 \leq n \leq 10^5)\)条平行于\(x\)轴的线段,接下来有\(m\)次射击\(x \, a \, b \, c\). 每次射击会获得一定的分数 ...
- HDU 4866 Shooting(主席树)题解
题意:在一个射击游戏里面,游戏者可以选择地面上[1,X]的一个点射击,并且可以在这个点垂直向上射击最近的K个目标,每个目标有一个价值,价值等于它到地面的距离.游戏中有N个目标,每个目标从L覆盖到R,距 ...
- hdu 5111 树链剖分加函数式线段树
这题说的是给了两棵树,各有100000 个节点,然后Q个操作Q<=50000; 每个操作L1 R1 L2 R2.因为对于每棵树都有一个与本棵树其他点与众不同的值, 最后问 在树上从L1到R1这条 ...
- 学习笔记--函数式线段树(主席树)(动态维护第K极值(树状数组套主席树))
函数式线段树..资瓷 区间第K极值查询 似乎不过似乎划分树的效率更优于它,但是如果主席树套树状数组后,可以处理动态的第K极值.即资瓷插入删除,划分树则不同- 那么原理也比较易懂: 建造一棵线段树(权值 ...
- POJ2104 K-th number 函数式线段树
很久没打代码了,不知道为什么,昨天考岭南文化之前突然开始思考起这个问题来,这个问题据说有很多种方法,划分树什么的,不过对于我现在这种水平还是用熟悉的线段树做比较好.这到题今年8月份的时候曾经做过,那个 ...
- BZOJ 3123 森林(函数式线段树)
题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=3123 题意: 思路:总的来说,查询区间第K小利用函数式线段树的减法操作.对于两棵树的合并 ...
- BZOJ 3207 花神的嘲讽计划Ⅰ(函数式线段树)
题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=3207 题意:给出一个数列,若干询问.每个询问查询[L,R]区间内是否存在某个长度为K的子 ...
- [Usaco2014 Open Gold ]Cow Optics (树状数组+扫描线/函数式线段树)
这道题一上手就知道怎么做了= = 直接求出原光路和从目标点出发的光路,求这些光路的交点就行了 然后用树状数组+扫描线或函数式线段树就能过了= = 大量的离散+模拟+二分什么的特别恶心,考试的时候是想到 ...
随机推荐
- apktool 反翻译错误
-出现 UndefinedResObject Exception : 这是因为被反编译的apk中有当前的framework不支持的属性:解决方式如下: 1.删除C:\Users\Administrat ...
- 百度apistore第三方登陆
最近做一个个人博客,其中的登陆模块我想使用第三方登陆来做.上网搜一下有好多例子,但是大多数都是一个网站的第三方登陆,如QQ.微博.人人,没有集成的组件,于是就在网上搜一下百度的apistore,百度果 ...
- git配置ssh
$ git config --global user.name "yourname"$ git config --global user.email "youremail ...
- linux之awk
相较于sed 常常作用于一整个行的处理,awk 则比较倾向于一行当中分成数个『字段』来处理. 因此,awk 相当的适合处理小型的数据数据处理呢! awk 通常运作的模式是这样的: [root@linu ...
- IOS 特定于设备的开发:使用加速能力“向上定位”
iPhone提供了3个机载的传感器,用于沿着iPhone的3根相互垂直的轴(左/右(x轴).上/下(y轴)和前/后(z轴))度量加速能力.这些值指示作用于iPhone的力,它们来自重力和用户移动.可以 ...
- 在FL2440上使用kei MDK 调试程序(J-link)
<一>新建一个工程 单击Project ->New µVision Project...菜单项 <二>选择CPU 这里我们选择三星的2440A 点击OK后会提示你是否添加 ...
- Mybatis的ResultMap的使用(转)
本篇文章通过一个实际工作中遇到的例子开始吧: 工程使用Spring+Mybatis+Mysql开发.具体的业务逻辑很重,对象之间一层一层的嵌套.和数据库表对应的是大量的model类,而和前端交互的是V ...
- RedisService
package com.sprucetec.bone.common.redis;import com.alibaba.fastjson.JSON;import org.springframework. ...
- pv ticketlock解决虚拟环境下的spinlock问题
最近看邮件,有注意到pv ticketlock相关的消息,貌似jeremy 几年前的东东,终于将要被收录到linux 3.12里面. 先说下pv ticketlock这东西,http://blog.x ...
- 现场故障案例:AIX安装Oracle10G runInstaller弹出错误一例
AIX安装Oracle10G runInstallert弹出错误一例 环境: 系统:AIX5300-08 数据库:Oracle 10g(64bit) AIX客户机卸载oracle软件后,又一次安装or ...