【BZOJ 2453】 维护队列

【题目链接】          

            https://www.lydsy.com/JudgeOnline/problem.php?id=2453

【算法】                

          带修改的莫队算法  

          当块的大小为N^(2/3)时,时间复杂度为 : O(n^(5/3))

          但本题,当块的大小为sqrt(N)时,能够达到更优的复杂度

【代码】

             

#include<bits/stdc++.h>
using namespace std;
#define MAXN 10010
const int MAXC = 1e6 + 5;

int i,len,x,y,sum,l,r,n,now,qnum,m,cnt;
int a[MAXN],block[MAXN],s[MAXC],ans[MAXN];
char op[5];

template <typename T> inline void read(T &x)
{
    int f = 1; x = 0;
    char c = getchar();
    for (; !isdigit(c); c = getchar()) { if (c == '-') f = -f; }
    for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0';
    x *= f;
}
template <typename T> inline void write(T x)
{
    if (x < 0)
    {
        putchar('-');
        x = -x;
    }
    if (x > 9) write(x/10);
    putchar(x%10+'0');
}
template <typename T> inline void writeln(T x)
{
    write(x);
    puts("");
}
struct info
{
    int x,y,last;
} c[MAXN];
struct Query
{
    int x,y,id,cur;
} q[MAXN];

inline bool cmp(Query a,Query b)
{
    if (block[a.x] == block[b.x])
    {
        if (block[a.y] == block[b.y]) return a.cur < b.cur;
        else return block[a.y] < block[b.y];
    } else return block[a.x] < block[b.x];        
}
inline void add(int x)
{
    s[a[x]]++;
    if (s[a[x]] == 1) sum++;    
}
inline void dec(int x)
{
    s[a[x]]--;
    if (s[a[x]] == 0) sum--;
}
inline void worka(int now)
{
    int x = c[now].x,y = c[now].y;
    if (x >= l && x <= r) dec(x);
    c[now].last = a[x];
    a[x] = y;
    if (x >= l && x <= r) add(x);    
}
inline void workb(int now)
{
    int x = c[now].x,y = c[now].y;
    if (x >= l && x <= r) dec(x);
    a[x] = c[now].last;
    if (x >= l && x <= r) add(x);
}

int main()
{
    
    read(n); read(m);
    len = sqrt(n);
    for (i = 1; i <= n; i++) block[i] = (i - 1) / len + 1;
    for (i = 1; i <= n; i++) read(a[i]);
    for (i = 1; i <= m; i++)
    {
        scanf("%s",&op);
        read(x); read(y);
        if (op[0] == 'Q') q[++qnum] = (Query){x,y,qnum,cnt};
        else c[++cnt] = (info){x,y,0};    
    }
    sort(q+1,q+qnum+1,cmp);
    l = 1; r = 0; now = 0; sum = 0;
    for (i = 1; i <= qnum; i++)
    {
        for (; r < q[i].y; r++) add(r+1);        
        for (; r > q[i].y; r--) dec(r);
        for (; l < q[i].x; l++) dec(l);
        for (; l > q[i].x; l--) add(l-1);
        for (now; now < q[i].cur; now++) worka(now+1);
        for (now; now > q[i].cur; now--) workb(now);
        ans[q[i].id] = sum;
    }
    for (i = 1; i <= qnum; i++) printf("%d\n",ans[i]);

    return 0;
}

 

posted @ 2018-07-15 11:59  evenbao  阅读(143)  评论(0编辑  收藏  举报