题意:
。。
这道是zstu2015校赛题。。
传送
思路:
对于第一个询问,先维护差分序列,然后求对差分序列求两次前缀和得到前缀和。
对第二个询问。
假设用pair<int, int>
来表示区间。
先把表白计划按girl分开存,对每个girl处理出她不发好人卡的区间。
这一步是 O(mlogm),m 为区间数
建一个线段树,节点 v(l,r)包含girl_l到girl_r的不发好人卡的区间,注意要去掉那些被其他区间完全包含的区间。
处理出来的区间全部都从小到大排序。
每一层所有节点包含的区间数 O(m)
所以这一步时间复杂度 O(mlogmlogn),空间 O(mlogn)
最后处理查询,可以用二分地在一个有序的区间序列里查找是否包含某个区间。而找id最小的就很容易了。。
不错的一道数据结构题,考察了基本的对区间的模拟操作,合并,查找,去重等。也对线段树有很好的利用。
const int N = 80005;
typedef pair<int, int> pii;
typedef long long LL;
LL prf[N];
vector<pii> gl[N];
int n, m, t;
void range_inv(vector<pii>& v, int t) {
vector<pii> tmp;
int cur = 1;
for(int i = 0; i < v.size(); ++ i) {
if ( cur < v[i].first ) {
tmp.push_back( make_pair(cur, v[i].first - 1) );
}
cur = max ( cur, v[i].second + 1 );
}
if ( cur <= t ) tmp.push_back( make_pair(cur, t) );
tmp.swap(v);
}
bool contain(const vector<pii>& v, int l, int r) {
int pos = upper_bound( v.begin(), v.end(), make_pair(l, INT_MAX) ) - v.begin();
if ( !pos || v[pos - 1].second < r ) return 0;
return 1;
}
vector<pii> tr[N<<2];
int qL, qR;
#define lc o<<1
#define rc o<<1|1
void build(int o, int l, int r) {
vector<pii>& v = tr[o];
if ( l == r ) {
v = gl[l];
} else {
int m = (l + r) >> 1;
build(lc, l, m);
build(rc, m + 1, r);
vector<pii>().swap(v);
rep(i, l, r) v.insert(v.end(), gl[i].begin(), gl[i].end());
sort(v.begin(), v.end());
int top = 1;
for (int i = 1; i < v.size(); ++ i)
if ( v[i].second > v[top - 1].second ) {
if ( v[i].first == v[top - 1].first ) {
v[top - 1].second = v[i].second;
} else {
v[top ++] = v[i];
}
}
v.resize(top);
}
}
int query(int o, int l, int r) {
if ( l == r ) return l;
int m = (l + r) >> 1;
if ( contain(tr[lc], qL, qR) )
return query(lc, l, m);
return query(rc, m + 1, r);
}
int main() {
#ifdef _LOCA_ENV_
freopen("input.in", "r", stdin);
#endif // _LOCA_ENV
while ( scanf("%d%d%d", &n, &m, &t) != EOF ) {
memset(prf, 0, sizeof(prf));
rep(i, 1, n) vector<pii>().swap(gl[i]);
rep(i, 1, m) {
int l, r, x;
scanf("%d%d%d", &l, &r, &x);
prf[l] += 1;
prf[r+1] -= 1;
gl[x].push_back( make_pair(l, r) );
}
rep(i, 1, t) prf[i] += prf[i-1];
rep(i, 1, t) prf[i] += prf[i-1];
rep(i, 1, n) {
sort(gl[i].begin(), gl[i].end());
range_inv(gl[i], t);
}
build(1, 1, n);
int z = 0, q;
scanf("%d", &q);
rep(o, 1, q) {
int l, r;
scanf("%d%d", &l, &r);
l += z, r += z;
if ( r > t ) {
l = t - ( r - l );
r = t;
}
qL = l, qR = r;
if ( !contain(tr[1], l, r) )
z = 0;
else
z = query(1, 1, n);
printf("%lld %d\n", prf[r] - prf[l-1], z);
}
}
return 0;
}