bzoj 2120

2120: 數顏色

Time Limit: 6 Sec  Memory Limit: 259 MB
Submit: 6430  Solved: 2562
[Submit][Status][Discuss]

Description

墨墨購買了一套N支彩色畫筆(其中有些顏色可能相同),擺成一排,你須要回答墨墨的提問。墨墨會像你發佈以下指令: 一、 Q L R表明詢問你從第L支畫筆到第R支畫筆中共有幾種不一樣顏色的畫筆。 二、 R P Col 把第P支畫筆替換爲顏色Col。爲了知足墨墨的要求,你知道你須要幹什麼了嗎?php

Input

第1行兩個整數N,M,分別表明初始畫筆的數量以及墨墨會作的事情的個數。第2行N個整數,分別表明初始畫筆排中第i支畫筆的顏色。第3行到第2+M行,每行分別表明墨墨會作的一件事情,格式見題幹部分。ios

Output

對於每個Query的詢問,你須要在對應的行中給出一個數字,表明第L支畫筆到第R支畫筆中共有幾種不一樣顏色的畫筆。數組

Sample Input

6 5
1 2 3 4 5 5
Q 1 4
Q 2 6
R 1 2
Q 1 4
Q 2 6

Sample Output

4
4
3
4

HINT

 

對於100%的數據,N≤10000,M≤10000,修改操做很少於1000次,全部的輸入數據中出現的全部整數均大於等於1且不超過10^6。ui


2016.3.2新加數據兩組by Nano_Apespa

代碼:
//注意到顏色範圍只有1e6,修改操做不超過1000。分塊,用pre[i]記錄col[i]上一次出現的位置,每一塊中的pre數組
//從小到大排序,而後二分找到有幾個的pre在詢問區間的左端點的左邊就是有幾種數,兩邊的區間暴力找。修改時暴力
//修改,更新pre,nex。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const int MAXN=10009;
int n,m,B,cnt,block[MAXN],pre[MAXN],nex[MAXN],last[1000009],p[MAXN],col[MAXN];
void resort(int x)
{
    int l=(x-1)*B+1,r=min(n,x*B);
    for(int i=l;i<=r;i++) p[i]=pre[i];
    sort(p+l,p+r+1);
}
void build()
{
    for(int i=1;i<=n;i++){
        scanf("%d",&col[i]);
        pre[i]=last[col[i]];
        if(last[col[i]]) nex[last[col[i]]]=i;
        last[col[i]]=i;
        block[i]=(i-1)/B+1;
    }
    for(int i=1;i<=cnt;i++) resort(i);
}
int find(int x,int ql)
{
    int l=(x-1)*B+1,r=x*B,ans=0;
    int st=l;
    while(l<=r){
        int mid=(l+r)>>1;
        if(p[mid]<ql) { ans=mid-st+1;l=mid+1; }
        else r=mid-1;
    }
    return ans;
}
int query(int ql,int qr)
{
    int s=0;
    for(int i=ql;i<=min(n,block[ql]*B);i++)
        if(pre[i]<ql) s++;
    if(block[ql]!=block[qr]){
        for(int i=(block[qr]-1)*B+1;i<=qr;i++)
            if(pre[i]<ql) s++;
    }
    for(int i=block[ql]+1;i<block[qr];i++) s+=find(i,ql);
    return s;
}
void update(int x,int y)
{
    col[x]=y;
    if(nex[x]) { pre[nex[x]]=pre[x];resort(block[nex[x]]); }
    if(pre[x]) nex[pre[x]]=nex[x];
    int pr=0,ne=0;
    for(int i=x-1;i>=1;i--)
        if(col[i]==y) { pr=i;break; }
    for(int i=x+1;i<=n;i++)
        if(col[i]==y) { ne=i;break; }
    pre[x]=pr;nex[x]=ne;
    resort(block[x]);
    if(pr) nex[pr]=x;
    if(ne) { pre[ne]=x;resort(block[ne]); }
}
int main()
{
    //freopen("in.txt","r",stdin);
    memset(last,0,sizeof(last));
    scanf("%d%d",&n,&m);
    B=sqrt(n);
    cnt=n/B+(n%B!=0);
    build();
    while(m--){
        char ch[3];
        int x,y;
        scanf("%s%d%d",ch,&x,&y);
        if(ch[0]=='Q') printf("%d\n",query(x,y));
        else update(x,y);
    }
    return 0;
}
相關文章
相關標籤/搜索