1. 程式人生 > >牛客網暑期ACM多校訓練營(第六場) I Team Rocket(線段樹)

牛客網暑期ACM多校訓練營(第六場) I Team Rocket(線段樹)

div 訓練 mem 線段樹 acm its cas 大於 pan

題意:

給定n個區間, m次詢問, 每次詢問給一個點, 問這個點在哪些區間內, 然後刪掉這些區間。

分析:

將n個區間按L大小升序排列, 然後將這些區間視為點構建一棵n個點的線段樹, 樹的節點記錄這個區間的[l, r] 和按題目輸入順序排列的index

只有葉子節點的l, r代表這個區間本身, 他們的父親更新他們兒子的最大r用於剪枝 (如果這個點所有兒子的最大R都小於查詢的點, 就不用查了)

接下來只要二分出左區間大於x的那個區間的pos, 那麽查詢區間就是(1~pos)中有哪些點的右區間大於x, 記錄答案並修改右區間即可。

#include <bits/stdc++.h>
using
namespace std; const int maxN = 2e5 + 7; const int INF = 2e9 + 7; int n, m, x, y, pos, t, cancel; long long res; int ans[maxN]; struct Interval { int l, r, index; bool operator < (const Interval& a)const { return l < a.l; } } travel[maxN], tree[maxN * 4]; void build(int
treeIndex, int L, int R) { // printf("%d %d\n", L , R); if(L == R) { tree[treeIndex].l = travel[L].l; tree[treeIndex].r = travel[L].r; tree[treeIndex].index = travel[L].index; return; } int mid = (L + R) / 2;#include <bits/stdc++.h> using namespace std;
const int maxN = 2e5 + 7; const int INF = 2e9 + 7; int n, m, x, y, pos, t, cancel; long long res; int ans[maxN]; struct Interval { int l, r, index; bool operator < (const Interval& a)const { return l < a.l; } } travel[maxN], tree[maxN * 4]; void build(int treeIndex, int L, int R) { if(L == R) { tree[treeIndex].l = travel[L].l; tree[treeIndex].r = travel[L].r; tree[treeIndex].index = travel[L].index; return; } int mid = (L + R) / 2; int lSon = treeIndex * 2, rSon = treeIndex * 2 + 1; build(lSon, L, mid); build(rSon, mid + 1, R); tree[treeIndex].r = max(tree[lSon].r, tree[rSon].r); } void query(int treeIndex, int L, int R) { if(tree[treeIndex].r < x) return; if(L == R) { cancel++; int inIndex = tree[treeIndex].index; res = ((long long)res * inIndex) % 998244353; tree[treeIndex].r = -INF; ans[inIndex] = t; return; } int mid = (L + R) / 2; int lSon = treeIndex * 2, rSon = treeIndex * 2 + 1; query(lSon, L, mid); if(pos > mid) query(rSon, mid + 1, R); tree[treeIndex].r = max(tree[lSon].r, tree[rSon].r); } int main() { int T; scanf("%d", &T); for(int kase = 1; kase <= T; kase++) { printf("Case #%d:\n", kase); memset(ans, 0, sizeof(ans)); memset(tree, 0, sizeof(tree)); memset(travel, 0 , sizeof(travel)); scanf("%d %d", &n, &m); for(int i = 1; i <= n; i++) { scanf("%d %d", &travel[i].l, &travel[i].r); travel[i].index = i; } sort(travel + 1, travel + 1 + n); build(1, 1, n); res = 0; for(t = 1; t <= m; t++) { scanf("%d", &y); x = y ^ res; pos = upper_bound(travel + 1, travel + 1 + n, (Interval) {x,0,0}) - (travel + 1); cancel = 0, res = (long long)1;//乘積初始化為1 if(pos > 0) // pos等於0說明沒有任何一個左區間比x小 query(1, 1, n);//int treeIndex, int L, int R printf("%d\n", cancel); if(!cancel) res = 0; } printf("%d", ans[1]); for(int i = 2; i <= n; i++) { printf(" %d", ans[i]); } printf("\n"); } return 0; }

牛客網暑期ACM多校訓練營(第六場) I Team Rocket(線段樹)