#include<cstdio> #include<cstring> #include<algorithm> #include<vector> #include<queue> #include<string> using namespace std; #define rep(frep,ss,tt) for (frep=ss;frep<=tt;++frep) #define drep(frep,tt,ss) for (frep=tt;frep>=ss;--frep) #define inf 0x3f3f3f3f #define N 100001 #define num(x) T[x].num #define ls(x) T[x].ls #define rs(x) T[x].rs struct Tree{ int num,ls,rs; }T[N*20]; int sz,n,m; int a[N],p[N],hash[N],root[N]; inline void insert(int brt,int &rt,int l,int r,int x){ //注意这里的 &符号,可以修改外部变量 rt=++sz; T[rt]=T[brt]; ++num(rt); if (l==r) return; int mid=(l+r)>>1; if (x<=mid) insert(ls(brt),ls(rt),l,mid,x); else insert(rs(brt),rs(rt),mid+1,r,x); } int query(int brt,int rt,int l,int r,int k){ if (l==r) return l; int t=num(ls(rt))-num(ls(brt)); int mid=(l+r)>>1; if (t>=k) return query(ls(brt),ls(rt),l,mid,k); else return query(rs(brt),rs(rt),mid+1,r,k-t); } bool cmp(int i,int j){ return a[i]<a[j];} int main(){ scanf("%d%d",&n,&m); int i,x,y,k; rep(i,1,n) scanf("%d",&a[i]),p[i]=i; sort(p+1,p+1+n,cmp); rep(i,1,n) hash[p[i]]=i; //离散化 rep(i,1,n) insert(root[i-1],root[i],1,n,hash[i]); rep(i,1,m){ scanf("%d%d%d",&x,&y,&k); int f=query(root[x-1],root[y],1,n,k); printf("%d\n",a[p[f]]); } return 0; }
分析
坐标范围不大,可以不用离散化,省点时间
这题改了2天又是TLE又是MLE的= =
线段按d从小到大依次插入,建立n棵线段树
维护的是区间,所以用打tag的方式,涉及到标记下传的问题,不过这题只有加法操作,一路加下去就好了可以不用下传
每次查询一个位置,我们用二分查找对应的线段树,这颗树的这个位置上有<=k条线段(可能有不足k条),然后在这颗树上统计得分即可
这题数组需要开蛮大的,用结构体好像会浪费内存?!= =分成几个数组就过了ORZ
代码
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define rep(frep,ss,tt) for (frep=ss;frep<=tt;++frep) #define drep(frep,tt,ss) for (frep=tt;frep>=ss;--frep) #define inf 0x3f3f3f3f #define NN 100005 #define MAXN 5900100 struct Seg{ int l,r,d; }seg[NN]; int ls[MAXN],rs[MAXN],num[MAXN]; long long sum[MAXN]; int tot,sz,N,X,M,root[NN]; long long P; bool cmp(const Seg &a,const Seg &b){ return a.d<b.d || (a.d==b.d && a.l<b.l) || (a.d==b.d && a.l==b.l && a.r<b.r); } inline void insert(int brt,int &rt,int l,int r,int s,int t,int d){ rt=++sz; sum[rt]=sum[brt]; num[rt]=num[brt]; ls[rt]=ls[brt]; rs[rt]=rs[brt]; if (s<=l && r<=t){ sum[rt]+=d; num[rt]++; return; } int mid=(l+r)>>1; if (s<=mid) insert(ls[brt],ls[rt],l,mid,s,t,d); if (t>mid) insert(rs[brt],rs[rt],mid+1,r,s,t,d); } int Num_query(int rt,int l,int r,int x){ int ans=num[rt]; if (l!=r){ int mid=(l+r)>>1; if (x<=mid) ans+=Num_query(ls[rt],l,mid,x); else ans+=Num_query(rs[rt],mid+1,r,x); } return ans; } long long Sum_query(int rt,int l,int r,int x){ long long ans=sum[rt]; if (l!=r){ int mid=(l+r)>>1; if (x<=mid) ans+=Sum_query(ls[rt],l,mid,x); else ans+=Sum_query(rs[rt],mid+1,r,x); } return ans; } int search(int pos,int num){ int l=1,r=N,mid; while (l<=r){ mid=(l+r)>>1; int calc=Num_query(root[mid],1,X,pos); if (calc==num) return mid; if (calc<num) l=mid+1; else r=mid-1; } return l; } int main(){ //freopen("xx.in","r",stdin); int i,x; long long a,b,c; while (~scanf("%d%d%d%I64d",&N,&M,&X,&P)){ sz=0; rep(i,1,N) scanf("%d%d%d",&seg[i].l,&seg[i].r,&seg[i].d); sort(seg+1,seg+1+N,cmp); rep(i,1,N) insert(root[i-1],root[i],1,X,seg[i].l,seg[i].r,seg[i].d); long long pre=1,k; rep(i,1,M){ scanf("%d%I64d%I64d%I64d",&x,&a,&b,&c); k=(a*pre+b)%c; if (!k) { puts("0"); pre=0; continue; } int pos=search(x,k); long long ans=Sum_query(root[pos],1,X,x); if (pre>P) ans<<=1; printf("%I64d\n",ans); pre=ans; } } }