将所有目标与起点线的距离离散化作为下标,建立函数式线段树,将距离按区间端点从1到X的顺序加入函数式线段树,左端点+1,右端点-1,记录区间元素的距离和,以及元素的个数。对于在x位置的询问,找到其对应的端点,这个可以二分找到,然后在该端点对应的线段树上进行二分查找求解,最后判断前一个答案与P的大小得到当前问题的答案。。。。注意有线段可能完全重合。。。
#include <iostream>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <bitset>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <climits>
#include <cstdlib>
#include <cmath>
#include <time.h>
#define maxn 100005
#define eps 1e-10
#define mod 1000000009
#define INF 99999999
#define lowbit(x) (x&(-x))
//#define lson o<<1, L, mid
//#define rson o<<1 | 1, mid+1, R
typedef long long LL;
//typedef int LL;
using namespace std;
struct Edge
{
int a, d, op;
}e[maxn<<1];
int dd[maxn];
int dcnt;
struct node
{
node *lson, *rson;
LL val, sum;
void maintain(void)
{
sum = lson->sum + rson->sum;
val = lson->val + rson->val;
}
}*root[maxn<<2], C[maxn*40], *null, *top;
int n, m, v;
int x, p;
int cmp(int a, int b)
{
return a<b;
}
int cmp1(Edge a, Edge b)
{
return a.a < b.a;
}
void read(void)
{
int i, aa, bb, d, cont = 0;
dcnt = 0;
for(i = 0; i < n; i++) {
scanf("%d%d%d", &aa, &bb, &d);
e[cont].a = aa, e[cont].d = d, e[cont].op = 1, cont++;
e[cont].a = bb+1, e[cont].d = d, e[cont].op = -1, cont++;
dd[++dcnt] = d;
}
n = cont;
}
void work(void)
{
int i, j;
sort(dd+1, dd+1+dcnt, cmp);
for(i = 2, j = 2; i <= dcnt; i++)
if(dd[i] == dd[j])
dd[j++] = dd[i];
dcnt = j-1;
sort(e, e+n, cmp1);
}
int search(int tmp)
{
int bot = 1, top = dcnt, mid;
while(top >= bot) {
mid = (top+bot)>>1;
if(dd[mid] == tmp) break;
if(dd[mid] > tmp) top = mid-1;
else bot = mid+1;
}
return mid;
}
void init(void)
{
top = C;
null = top++;
null->val = null->sum = 0;
null->lson = null->rson = NULL;
}
node* build(int L, int R)
{
node *newroot = top++;
newroot->val = newroot->sum = 0;
if(L == R) {
newroot->lson = newroot->rson = null;
return newroot;
}
int mid = (L+R)>>1;
newroot->lson = build(L, mid);
newroot->rson = build(mid+1, R);
return newroot;
}
node* updata(node* o, int d, int L, int R)
{
node *now = top++;
if(L == R){
now->val = o->val + d;
now->sum = o->sum + dd[v]*d;
now->lson = now->rson = null;
return now;
}
int mid = (L+R)>>1;
if(v <= mid) {
now->lson = updata(o->lson, d, L, mid);
now->rson = o->rson;
}
else {
now->lson = o->lson;
now->rson = updata(o->rson, d, mid+1, R);
}
now->maintain();
return now;
}
LL kth(node *o, int k)
{
if(o->lson == null && o->rson == null) {
if(o->val != 0) return (LL)k*o->sum/o->val;
else return 0;
}
if(k <= o->lson->val) return kth(o->lson, k);
return o->lson->sum + kth(o->rson, k - o->lson->val);
}
void solve(void)
{
root[0] = build(1, dcnt);
for(int i = 1, j = 0; i <= x; i++) {
root[i] = root[i-1];
while(j<n && e[j].a <= i) {
v = search(e[j].d);
root[e[j].a] = updata(root[e[j].a], e[j].op, 1, dcnt);
j++;
}
}
}
/*
void debug(void)
{
for(int i = 0; i <= x; i++)
printf("AAA %d %d BBB\n", root[i]->val, root[i]->sum);
}
*/
void task(void)
{
int k;
LL xx, a, b, c, pre = 1, now;
while(m--) {
scanf("%I64d%I64d%I64d%I64d", &xx, &a, &b, &c);
k = (a*pre + b)%c;
now = kth(root[xx], k);
if(pre > p) now*=2;
printf("%I64d\n", pre = now);
}
}
int main(void)
{
while(scanf("%d%d%d%d", &n, &m, &x, &p)!=EOF) {
init();
read();
work();
solve();
task();
}
return 0;
}