查询区间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;
}