The number of colors (Los Valley -P1903)

Title Description

Ink ink bought a N branch color brush (some of which may be the same color), placed in a row, you need to answer questions ink ink. Ink ink will be released the following instructions to you:

1, QLR ask you on behalf of a total of brush several different colors of brushes from L to R brushes in the first.

2, RP Col brushes replace the color of P Col.

In order to meet the requirements of ink in the ink, you know you need to do it?

Input and output formats

Input formats:

Line 1 two integers N, M, representing the number of the initial number of ink in the ink pen and do things.

Row 2 N integers, representing the initial i-th row branched brush pen color.

The third row to the 2 + M rows, each row representing the ink in the ink will do a thing, formatted as casual working portion.

Output formats:

For each query Query, you need to give a number in the corresponding row, L represents the brushes to a total of R brushes brush several different colors.

Sample input and output

Input Sample # 1:

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

Output Sample # 1:

4
4
3
4

Ideas: Mo with a repair team title template

Source

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<utility>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
#define PI acos(-1.0)
#define E 1e-9
#define INF 0x3f3f3f3f
#define LL long long
const int MOD=10007;
const int N=1000000+5;
const int dx[]= {-1,1,0,0};
const int dy[]= {0,0,-1,1};
using namespace std;

struct Node{
    int l,r;//询问的左右端点
    int time;//时间维度
    int id;//询问的编号
}q[N];
struct Change{
    int pos;//要修改的位置
    int col;//要改成的值
}c[N];
int n,m,a[N];
int block;//分块
int numQ,numC;//查询、修改操作的次数
LL ans,cnt[N];
LL res[N];

bool cmp(Node a,Node b){//排序
    return (a.l/block)^(b.l/block) ? a.l<b.l : ((a.r/block)^(b.r/block)?a.r<b.r:a.time<b.time);
}

void add(int x){//统计新的,根据具体情况修改
    if(cnt[x]==0)
        ans++;
    cnt[x]++;

}
void del(int x){//减去旧的,根据具体情况修改
    cnt[x]--;
    if(cnt[x]==0)
        ans--;
}
void change(int x,int ti){//改变时间轴
    if(c[ti].pos>=q[x].l&&c[ti].pos<=q[x].r){
        del(a[c[ti].pos]);//删除指定位置上的值
        add(c[ti].col);//统计新的数
    }
    swap(c[ti].col,a[c[ti].pos]);//直接互换,下次执行时必定是回退这次操作
}
int main(){
    while(scanf("%d%d",&n,&m)!=EOF){
        ans=0;
        numQ=0;
        numC=0;
        memset(cnt,0,sizeof(cnt));
        block=pow(n,0.66666);//分块

        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);

        for(int i=1;i<=m;i++){
            char op[10];
            scanf("%s",op);
            if(op[0]=='Q'){//查询操作
                ++numQ;//查询操作次数+1
                scanf("%d%d",&q[numQ].l,&q[numQ].r);
                q[numQ].id=numQ;//序号
                q[numQ].time=numC;//时间轴
            }
            else{//修改操作
                ++numC;//修改操作次数+1
                scanf("%d%d",&c[numC].pos,&c[numC].col);
            }
        }
        sort(q+1,q+numQ+1,cmp);//对询问进行排序
        int l=1,r=0,time=0;//左右指针与时间轴
        for(int i=1;i<=numQ;i++){
            int ql=q[i].l,qr=q[i].r;//询问的左右端点
            int qtime=q[i].time;//询问的时间轴
            while(l>ql) add(a[--l]);//[l-1,r,time]
            while(l<ql) del(a[l++]);//[l+1,r,time]
            while(r<qr) add(a[++r]);//[l,r+1,time]
            while(r>qr) del(a[r--]);//[l,r-1,time]
            while(time<qtime) change(i,++time);//[l,r,time+1]
            while(time>qtime) change(i,time--);//[l,r,time-1]
            res[q[i].id]=ans;//获取答案
        }

        for(int i=1;i<=numQ;i++)
            printf("%lld\n",res[i]);
    }
    return 0;
}

 

Released 1871 original articles · won praise 702 · Views 1.94 million +

Guess you like

Origin blog.csdn.net/u011815404/article/details/88317597