題意:
。。
這道是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;
}