https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&category=&problem=3767&mosmsg=Submission+received+with+ID+19859366
最近太久沒發文了=_=,最近應該會把最近寫的code慢慢放上來!
這題可以使用 待修改莫隊 來解答,複雜度是好的O(N ^ 5/3)
#include <iostream> #include <stdio.h> #include <algorithm> #include <cmath> #include <cstring> using namespace std; const int MAX_N = 5e4 + 6; const int MAX_M = 1e6 + 6; int cnt[MAX_M]; int s[MAX_N]; struct Query { int L,R,Lid,Rid,T,id; void give_val(int _L,int _R,int _Lid,int _Rid,int _T,int _id) { L = _L; R = _R; Lid = _Lid; Rid = _Rid; T = _T; id = _id; } bool operator<(const Query &q2) { if (Lid != q2.Lid) return Lid < q2.Lid; if (Rid != q2.Rid) return Rid < q2.Rid; return T < q2.T; } } query[MAX_N]; struct Modify { int pos,ori_val,after_val; void give_val(int _pos,int _ori_val,int _after_val) { pos = _pos; ori_val = _ori_val; after_val = _after_val; } } modify[MAX_N]; int ans[MAX_N]; int cur_ans; void add(int x) { if (cnt[x] == 0) cur_ans++; cnt[x]++; } void sub(int x) { if (cnt[x] == 1) cur_ans--; cnt[x]--; } void addTime(int T,int L,int R) { if (L <= modify[T].pos && modify[T].pos <= R) { sub(s[modify[T].pos]); add(modify[T].after_val); } s[modify[T].pos] = modify[T].after_val; } void subTime(int T,int L,int R) { if (L <= modify[T].pos && modify[T].pos <= R) { sub(s[modify[T].pos]); add(modify[T].ori_val); } s[modify[T].pos] = modify[T].ori_val; } int main () { int n,m; while (scanf("%d %d",&n,&m) != EOF) { memset(cnt,0,sizeof(cnt)); memset(ans,-1,sizeof(ans)); for (int i=1;n>=i;i++) { scanf("%d",&s[i]); } int T=-1; int qid=0; int B = pow(max(n,m),2.0/3.0); if (B<=0) B=1; for (int i=1;m>=i;i++) { getchar(); char c; int x,y; scanf("%c %d %d",&c,&x,&y); if (c=='Q') { x++; query[++qid].give_val(x,y,x/B,y/B,T,i); } else { x++; modify[++T].give_val(x,s[x],y); s[x] = y; } } sort(query+1,query+qid+1); int L=1,R=0; for (int i=1;qid >= i;i++) { if (query[i].L > query[i].R) { ans[query[i].id] = 0; continue; } while (query[i].R > R) add(s[++R]); while (query[i].L < L) add(s[--L]); while (query[i].R < R) sub(s[R--]); while (query[i].L > L) sub(s[L++]); while (query[i].T > T) addTime(++T,L,R); while (query[i].T < T) subTime(T--,L,R); ans[query[i].id] = cur_ans; } for (int i=1;m>=i;i++) { if (ans[i] != -1) printf("%d\n",ans[i]); } } }
或者是也可以用 "BIT 套 可持久化線段樹" (树状数组 + 主席树) 來解
#include <iostream> #include <stdio.h> #include <set> #include <map> #include <cassert> #include <cstring> using namespace std; const int MAX_N = 1e5 + 6; const int MAX_M = 3e5 + 6; struct Node { int lc,rc; int val; void give_val(int _lc,int _rc,int _val) { lc=_lc; rc=_rc; val = _val; } } node[300*MAX_N]; int bit_root[MAX_N],root[MAX_N]; int node_cnt; int getNode(int id) { int ret = ++node_cnt; node[ret] = node[id]; return ret; } void pull(int id) { node[id].val = node[node[id].lc].val + node[node[id].rc].val; } void init(int id,int L,int R) { if (L==R) { node[id].give_val(0,0,0); return; } node[id].give_val(++node_cnt,++node_cnt,0); int mid=(L+R)>>1; init(node[id].lc,L,mid); init(node[id].rc,mid+1,R); return; } void modify(int old_id,int new_id,int L,int R,int pos,int val) { if (L==R) { node[new_id].val += val; return; } int mid=(L+R)>>1; if (pos <= mid) { node[new_id].lc = getNode(node[old_id].lc); modify(node[old_id].lc,node[new_id].lc,L,mid,pos,val); } else { node[new_id].rc = getNode(node[old_id].rc); modify(node[old_id].rc,node[new_id].rc,mid+1,R,pos,val); } pull(new_id); return; } int query(int id,int L,int R,int l,int r) { if (l<=L && R<=r) return node[id].val; int mid=(L+R)>>1; if (mid + 1 > r) return query(node[id].lc,L,mid,l,r); else if (l > mid) return query(node[id].rc,mid+1,R,l,r); return query(node[id].lc,L,mid,l,r) + query(node[id].rc,mid+1,R,l,r); } set<int> st[MAX_M]; int last[MAX_N]; int s[MAX_N]; int n,q; typedef long long LL; void modify_bit(int L,int R,int pos,int val) { if (L>R) assert(0); for (int i=L;n>=i;i+=(i&(-i))) { modify(bit_root[i],bit_root[i],1,n,pos,val); } if (R==n) return; for (int i=R+1;n>=i;i+=(i&(-i))) { modify(bit_root[i],bit_root[i],1,n,pos,-val); } } int query_bit(int C,int L,int R) { int ret=0; for (int i=C;i>0;i-=(i&(-i))){ ret += query(bit_root[i],1,n,L,R); } return ret; } int main (){ while (scanf("%d %d",&n,&q) != EOF) { node_cnt = 0; memset(last,0,sizeof(last)); for (int i=0;MAX_M>i;i++) { st[i].clear(); } node[0].give_val(0,0,0); root[0] = ++node_cnt; init(root[0],1,n); map<int,int> mp; for (int i=1;n>=i;i++) { bit_root[i] = getNode(root[0]); } int id=1; for (int i=1;n>=i;i++) { int x; scanf("%d",&x); int ret=0; auto iter=mp.find(x); if (iter == mp.end()) { mp.insert(make_pair(x,id)); ret=id; id++; } else { ret=iter->second; } root[i] = getNode(root[i-1]); if (last[ret] == 0) { modify(root[i-1],root[i],1,n,i,1); } else { modify(root[i-1],root[i],1,n,i,1); modify(root[i],root[i],1,n,last[ret],-1); } last[ret] = i; st[ret].insert(i); s[i] = ret; } int pre_ans=0; for (int i=1;q>=i;i++) { char a; getchar(); int b,c; scanf("%c %d %d",&a,&b,&c); if (a=='Q') { b++; if (b>c) { puts("0"); continue; } pre_ans = query(root[c],1,n,b,c); pre_ans += query_bit(c,b,c); printf("%d\n",pre_ans); } else { b++; if (mp[c] == s[b]) continue; int del=s[b]; auto iter=st[del].find(b); int ed = n+1; auto iter2=iter; ++iter; if (iter != st[del].end()) ed = *(iter); //b ~ ed - 1 modify_bit(b,ed-1,b,-1); auto iter6 = iter2; if (iter2 != st[del].begin()) { int start=*(--iter2); modify_bit(b,ed-1,start,1); } st[del].erase(st[del].find(b)); //finish delete //now let's add int ret=0; auto iter3=mp.find(c); if (iter3 == mp.end()) { mp.insert(make_pair(c,id)); ret=id; id++; } else if (iter3->second == 0) { mp[c] = id; ret=id; id++; } else { ret=iter3->second; } st[ret].insert(b); auto iter4 = st[ret].find(b); ed = n+1; auto iter5 = iter4; ++iter4; if (iter4 != st[ret].end()) { ed = *(iter4); } modify_bit(b,ed-1,b,1); if (iter5 != st[ret].begin()) { int start = *(--iter5); modify_bit(b,ed-1,start,-1); } s[b] = ret; } } } }
沒有留言:
張貼留言