1. 程式人生 > >Codeforces 369 E 離線、思維

Codeforces 369 E 離線、思維

多少 void efi truct pan define 每次 排序 clu

E. Valera and Queries

題意:橫坐標軸上,給出 n 段區間(可交叉)。 有 m 個詢問,每次詢問給出多個點,求這 n 段區間有多少段至少包含了一個點。

tags:離線+樹狀數組

1】數據量太大,所以肯定離線處理。

2】給出的是區間,而詢問給出的是點,我們必須想辦法把詢問的點轉化為區間。所以對於每次給出的 k 個點,我們取出它們分割出的區間。

3】要求多少個區間包含了點,我們反過來求有多少個區間沒有包含任何點。如果給出的區間在分割出來的區間內部,那麽這個區間肯定就沒有包含這次詢問的點。

4】我們只要把所有的區間按左端點從大到小排序,再右端點從小到大排序。用樹狀數組維護給出區間的右端點即可。

#include<bits/stdc++.h>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define rep(i,a,b) for (int i=a; i<=b; ++i)
#define per(i,b,a) for (int i=b; i>=a; --i)
#define mes(a,b)  memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define MP make_pair
#define PB push_back
#define
fi first #define se second typedef long long ll; const int N = 1000005; int n, m, bit[N], cnt, ans[N]; struct Node { int l, r, id; bool friend operator< (Node a, Node b) { if(a.l==b.l && a.r==b.r) return a.id<b.id; if(a.l==b.l) return a.r<b.r;
return a.l > b.l; } } p[N<<2]; void Add(int x, int y) { for(int i=x; i<N; i+=i&-i) bit[i] += y; } int Sum(int x) { int sum = 0; for(int i=x; i; i-=i&-i) sum += bit[i]; return sum; } int main() { scanf("%d%d", &n, &m); rep(i,1,n) ++cnt, scanf("%d%d", &p[cnt].l, &p[cnt].r), p[cnt].id=0; int ti, pos, l; rep(i,1,m) { scanf("%d", &ti); l = 0; rep(j,1,ti) { scanf("%d", &pos); p[++cnt] = (Node){ l+1, pos-1, i }; l = pos; } p[++cnt] = (Node){ l+1, N-1, i }; } sort(p+1, p+1+cnt); rep(i,1,cnt) { if(p[i].id==0) Add(p[i].r, 1); else ans[p[i].id] += Sum(p[i].r); } rep(i,1,m) printf("%d\n", n-ans[i]); return 0; }

Codeforces 369 E 離線、思維