查询区间l,r 中 不同值的个数, 修改操作是 单点更新。
如果没有更新,此题直接 离线。
有更新的话,就只有 树状数组套 平衡树 或者 可持久化数据结构。
问题一 。统计 在 【1,l-1】中都多少个值没有出现在 【l,r】。也就是统计 【1,l-1】中有多少个值,在【1,r】中仅出现在 【1,l-1】。
统计 对于ai ,它的下次出现与ai 值相同的点的下标是多少。 相当于 把所有相同的值的下标放到同一棵set 中,查 i 的后继是多少。
所以按值构建2*n 棵set ,来维护2*n个值出现的下标。快速的找到后继。(值是离散化后的值,下标i,离散化后值 a, 那么st【a】中插入 i)。
序列n个点, 共n个线段树, 每个线段树中维护的是 是 又是后继的下标, 有点绕。
查询 【1,l-1】 查大于r的值有多少个,就是 问题一的解。
问题二 : 在区间 【1,r】中出现了多少个值, 在set 中查找如果是 begin() , 就是说最小的数, 那么+1 ,不是最小不加。
修改是个难点 :
问题一种 维护的是后继, 相当与 链表的修改,
删除点 a ,它的前驱的后继发生变化。
增添点a,增添后的前驱的后继也发生变化。
他这个点的前驱和后继发生变化。
这样 共需要 6次操作。
问题二中较简单。
这题AC的历程有点艰辛。 代码有点长
#include <vector> #include <list> #include <map> #include <set> #include <deque> #include <stack> #include <cstring> #include <bitset> #include <algorithm> #include <functional> #include <numeric> #include <utility> #include <sstream> #include <iostream> #include <iomanip> #include <cstdio> #include <cmath> #include <cstdlib> #include <ctime> #include <assert.h> #include <queue> #define REP(i,n) for(int i=0;i<n;i++) #define TR(i,x) for(typeof(x.begin()) i=x.begin();i!=x.end();i++) #define ALLL(x) x.begin(),x.end() #define SORT(x) sort(ALLL(x)) #define CLEAR(x) memset(x,0,sizeof(x)) #define FILLL(x,c) memset(x,c,sizeof(x)) using namespace std; const double eps = 1e-9; #define LL long long #define pb push_back const int maxn = 11000; int num[maxn]; int n , m; map<int ,int>mp; map<int,int>::iterator it; char op[maxn][4]; int t[maxn][3]; struct Node{ Node *l,*r; int sum; }; int tot; struct Seg{ Node nodes[maxn*60]; Node *null; Node *root[maxn]; int C; void init(){ C= 0; null = &nodes[C++]; null->l = null ->r = null; null->sum = 0; for(int i=1;i<=n;i++){ root[i] = &nodes[C++]; root[i]->l = null; root[i]->r = null; root[i]->sum = 0; } } Node *update(int pos,int left,int right,Node *root,int val){ Node * rt = root; if(rt == null){ rt = &nodes[C++]; rt->l = null; rt->r = null; rt->sum = 0; } if(left == right){ rt->sum +=val; return rt; } int mid = (left + right)/2; if(pos<=mid){ rt->l = update(pos,left,mid,rt->l,val); }else{ rt->r = update(pos,mid+1,right,rt->r ,val); } rt->sum = rt->l->sum + rt->r->sum ; return rt; } void update(int k,int pos,int val){ for(;k<=n;k+= k&(-k)){ update(pos,1,n+1,root[k],val); } } int query(int left ,int right,int L,int R,Node *root){ if(L>R)return 0; if(L<=left && right<=R){ return root->sum; } int mid = (left +right)/2; int ret = 0; if(L<=mid){ ret += query(left,mid,L,R,root->l); } if(R>=mid){ ret += query(mid+1,right,L,R,root->r); } return ret; } // 大于等于 a 的值 有多少个 int get(int k,int a){ int sum = 0 ; for(;k>0;k-=k&(-k)){ sum += query(1,n+1,a,n+1,root[k]); } return sum; } }S1,S2; set<int>st[maxn*2]; set<int>::iterator it1,it2,it3; int arr[maxn*2]; void inc(int k,int val){ if(k==0)return ; for(;k<=n;k+=k&(-k)){ arr[k]+=val; } } int get(int k){ int sum = 0; for(;k>0;k-=k&(-k)){ sum += arr[k]; } return sum; } void solve(){ S1.init(); //cout << "*********"<<endl; CLEAR(arr); for(int i=1;i<=tot;i++){ st[i].clear(); st[i].insert(n+1); } for(int i=1;i<=n;i++){ st[mp[num[i]]].insert(i); } // 初始化 arr for(int i=1;i<=n;i++){ int v = mp[num[i]]; it1 =st[v].lower_bound(i); if(it1==st[v].begin()){ // cout << i<< "***"<<endl; inc(i,1); } } for(int i=1;i<=n;i++){ int v = mp[num[i]]; it1 = st[v].upper_bound(i); S1.update(i,(*it1),1); //cout <<i << " "<< (int)(*it1)<<endl; } for(int i=1;i<=m;i++){ // cout << "starti"<<i<<endl; if(op[i][0]=='Q'){ int l = t[i][0]; int r = t[i][1]; // cout <<r << " wtf" <<mp[r]<<endl; int ans1 = S1.get(l-1,r+1); int ans2 = get(r); int ans = ans2 -ans1; // cout << ans2 << " "<< ans1<<endl; printf("%d\n",ans); }else{ int id = t[i][0]; int val = t[i][1]; if(num[id]==val)continue; // 实现 删除。 int v = mp[num[id]]; it1 = st[v].lower_bound(id); if(it1==st[v].begin()){ inc(id,-1); it1++; inc((*it1),1); } // SEGMENT it3 =it2 = it1 = st[v].lower_bound(id); it2++; S1.update(id,(*it2),-1); if(it1 != st[v].begin()){ it1--; S1.update((*it1),id,-1); S1.update((*it1),(*it2),1); } st[v].erase(it3); //geng新arr // 实现增添。 num[id] = val; v = mp[num[id]]; st[v].insert(id); //gengxin arr it1 =st[v].lower_bound(id); if(it1==st[v].begin()){ inc(id,1); it1++; inc((*it1),-1); }//SEGMENT it2 = it1 = st[v].lower_bound(id); it2++; if(it1 != st[v].begin()){ it1--; S1.update((*it1),(*it2),-1); S1.update((*it1),id,1); } S1.update(id,(*it2),1); } } } int idx[maxn*2]; int main(){ while(~scanf("%d%d",&n,&m)){ mp.clear(); for(int i=1;i<=n;i++){ scanf("%d",&num[i]); mp[num[i]]=1; } for(int i=1;i<=m;i++){ scanf("%s",op[i]); if(op[i][0]== 'Q'){ scanf("%d%d",&t[i][0],&t[i][1]); mp[t[i][1]]=1; }else{ scanf("%d%d",&t[i][0],&t[i][1]); mp[t[i][1]]=1; } } tot = 0; for(it = mp.begin(); it!= mp.end();it++){ tot ++ ; it->second = tot; idx[tot] = it->first; } tot++; solve(); } return 0; }