终于是解决了这个题目了
不过不知道下一次碰到主席树到底做不做的出来,这个东西稍微难一点就不一定能做得出
离散化+扫描线式的建树,所以对于某个坐标二分找到对应的那颗主席树,即搜索出结果即可(因为是扫描线式的建树,找到对应的树之后,就知道该点上面的线段有多少条了)
其他就是普通主席树的操作了
主席树里面维护两个东西,一个就是普通的那种在该区间的节点数目,另外就是权值
#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; }
HDU 4866 多校1 主席树+扫描线
时间: 2024-09-29 17:10:51