HDU 4866 多校1 主席树+扫描线

时间:2023-01-28 00:18:23

终于是解决了这个题目了

不过不知道下一次碰到主席树到底做不做的出来,这个东西稍微难一点就不一定能做得出

离散化+扫描线式的建树,所以对于某个坐标二分找到对应的那颗主席树,即搜索出结果即可(因为是扫描线式的建树,找到对应的树之后,就知道该点上面的线段有多少条了)

其他就是普通主席树的操作了

主席树里面维护两个东西,一个就是普通的那种在该区间的节点数目,另外就是权值

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define LL __int64
using namespace std;
const int N =200010;
const int maxn=N*100;
int n,m,x,p,tot;
int t[N],T[N];
int c1[maxn],lson[maxn],rson[maxn];
LL c2[maxn];
struct node2
{
int h,id;
bool operator < (const node2 rhs) const
{
return h<rhs.h;
}
}y[N];
struct node
{
int d,h,id;
bool operator < (const node& rhs)const{
if (d!=rhs.d) return d<rhs.d;
else return h>rhs.h;
}
}seg[N];
int build(int l,int r)
{
int rt=++tot;
c1[rt]=c2[rt]=0;
if (l>=r) return rt;
int mid=(l+r)>>1;
lson[rt]=build(l,mid);
rson[rt]=build(mid+1,r);
return rt;
}
int inserts(int rt,int pos,int v1,LL v2)
{
int newrt=++tot;
int tmp=newrt;
c1[newrt]=c1[rt]+v1;
c2[newrt]=c2[rt]+v2;
int l=1,r=n;
while (l<r)
{
int mid=(l+r)>>1;
if (pos<=mid){
lson[newrt]=++tot;
rson[newrt]=rson[rt];
newrt=lson[newrt];
rt=lson[rt];
r=mid;
}
else{
rson[newrt]=++tot;
lson[newrt]=lson[rt];
newrt=rson[newrt];
rt=rson[rt];
l=mid+1;
}
c1[newrt]=c1[rt]+v1;
c2[newrt]=c2[rt]+v2;
}
return tmp;
}
LL query(int rt,int pos)
{
LL ret=0;
int l=1,r=n;
while (l<r)
{
int mid=(l+r)>>1;
if (c1[lson[rt]]>=pos){
r=mid;
rt=lson[rt];
}
else
{
pos-=c1[lson[rt]];
ret+=c2[lson[rt]];
rt=rson[rt];
l=mid+1;
}
}
return c2[rt]+ret;
}
int main()
{
int loc,a,b,c;
while (scanf("%d%d%d%d",&n,&m,&x,&p)!=EOF)
{
int cnt=0;
tot=0;
for (int i=1;i<=n;i++){
scanf("%d%d%d",&a,&b,&c);
y[i].h=c;
y[i].id=i;
seg[++cnt]=(node){a,c,i};
seg[++cnt]=(node){b,-c,i};
}
sort(seg+1,seg+1+cnt);
sort(y+1,y+1+n);
for (int i=1;i<=n;i++){
t[y[i].id]=i;
}
T[0]=build(1,n);
for (int i=1;i<=cnt;i++){
if (seg[i].h>=0)
T[i]=inserts(T[i-1],t[seg[i].id],1,seg[i].h);
else
T[i]=inserts(T[i-1],t[seg[i].id],-1,seg[i].h);
}
LL pre=1;
while (m--)
{
scanf("%d%d%d%d",&loc,&a,&b,&c);
int K;
K=(a%c*pre%c+b)%c;
if (K==0){
puts("0");
pre=0;
continue;
}
int id;
int l=1,r=cnt+1;
while (l<r)
{
int mid=(l+r)>>1;
if (seg[mid].d<loc || (seg[mid].d==loc && seg[mid].h>=0)){
id=mid;
l=mid+1;
}
else{
r=mid;
}
}
LL ans=query(T[id],K);
if (pre>p) ans*=2;
pre=ans;
printf("%I64d\n",ans);
}
}
return 0;
}