cf#348-E. Little Artem and Time Machine-樹狀陣列+map節點(動態開點樹狀陣列)
阿新 • • 發佈:2018-12-24
http://codeforces.com/contest/669/problem/E
題意:
題意:有三個操作
1 x y,在第x秒插入一個y
2 x y,在第x秒移走一個y
3 x y, 問第x秒有多少個y
這個操作3可以問之前的時間,也可以問未來的時間。。。不太好離線搞
直接對數值y離散化,對於每個y建一個線段樹/樹狀陣列,維護的是時間這個維度,代表某段時間裡,這個y值的出現情況
例如在x秒插入一個 y,相當於在y的樹狀數組裡,x這個下標+1。
查詢x秒時y的數量,就是相當於在y的樹狀數組裡,【1,x】的和是什麼。
這裡對於每個值的樹狀陣列不可能真的開一個 1e9的 管轄區間,因為總的訪問量只有q,我們採用動態開點的方式即可,這裡為了實現方便直接用map替代,缺點是時間複雜度多了一個log,對於本題還算可以接受
時間是q*log1e9*log(玄學),第一個log是樹狀陣列的,第二個是map的(不會算)
程式碼:
#include <cstdio> #include <cmath> #include <cstring> #include <string> #include <algorithm> #include <queue> #include <map> #include <set> #include <vector> #include <iostream> using namespace std; const double pi=acos(-1.0); double eps=0.000001; typedef long long ll; struct node { int x,y,z; }; node tt[100005]; int bb[100005]; int idx[100005]; map<int ,int> tree[100050]; struct TREE { int lowbit(int x) { return x&-x; } void add(int x,int value,int id) { for (int i=x; i<=1e9; i=i+lowbit(i)) { tree[id][i]+=value; } } int get(int x,int id) { int sum=0; for (int i=x; i; i-=lowbit(i)) { sum+=tree[id][i]; } return sum; } }; TREE tp[100005]; int main() { int q; cin>>q; int x,y,z; for (int i=1; i<=q; i++) { scanf("%d%d%d",&x,&y,&z); tt[i].x=x,tt[i].y=y,tt[i].z=z; bb[i]=z; } sort(bb+1,bb+1+q); int cun=unique(bb+1,bb+1+q)-bb-1; for (int i=1; i<=q; i++) idx[i]=lower_bound(bb+1,bb+1+cun,tt[i].z)-bb; for (int i=1; i<=q; i++) { int x=tt[i].x,y=tt[i].y; if (x==1) tp[idx[i]].add(y,1,idx[i]); if (x==2 ) tp[idx[i]].add(y,-1,idx[i]); if (x==3) { int ret=tp[idx[i]].get(y,idx[i]); printf("%d\n",ret); } } return 0; }