zoukankan      html  css  js  c++  java
  • 【BZOJ2120】【块状链表】数颜色

    Description

    墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问。墨墨会像你发布如下指令: 1、 Q L R代表询问你从第L支画笔到第R支画笔中共有几种不同颜色的画笔。 2、 R P Col 把第P支画笔替换为颜色Col。为了满足墨墨的要求,你知道你需要干什么了吗?

    Input

    第1行两个整数N,M,分别代表初始画笔的数量以及墨墨会做的事情的个数。第2行N个整数,分别代表初始画笔排中第i支画笔的颜色。第3行到第2+M行,每行分别代表墨墨会做的一件事情,格式见题干部分。

    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。

    【分析】

    好吧,正解应该是树套树,但是...分块可以做....

    我的方法很暴力...改了暴力重建..居然还可以过。。

      1 /*
      2 宋代
      3 辛弃疾
      4 青玉案·元夕
      5 东风夜放花千树。更吹落、星如雨。宝马雕车香满路。凤箫声动,玉壶光转,一夜鱼龙舞。
      6 蛾儿雪柳黄金缕。笑语盈盈暗香去。众里寻他千百度。蓦然回首,那人却在,灯火阑珊处。
      7 */
      8 #include <iostream>
      9 #include <cstdio>
     10 #include <algorithm>
     11 #include <cstring>
     12 #include <vector>
     13 #include <utility>
     14 #include <iomanip>
     15 #include <string>
     16 #include <cmath>
     17 #include <queue>
     18 #include <assert.h>
     19 #include <map>
     20 #include <ctime>
     21 #include <cstdlib>
     22 #include <stack>
     23 #include <set> 
     24 #define LOCAL
     25 const int INF = 100000000;
     26 const int MAXN = 10000  + 10;
     27 const int maxnode = 20000 * 2 + 200000 * 20;
     28 const int MAXM= 1000000 + 10;
     29 using namespace std;
     30 int tot;
     31 int n, q, block_size;
     32 int data[MAXN];
     33 int belong[MAXN], block[MAXN];
     34 int t[MAXN],last[MAXM];
     35 
     36 
     37 //寻找第x块内有多少个比v要小的 
     38 int find(int x, int v){
     39     int l = (x - 1) * block_size + 1, r = min(x * block_size, n);
     40     int first = l;
     41     while (l <= r){
     42           int mid = (l + r) >> 1;
     43           if (block[mid] < v) l = mid + 1;
     44           else r = mid - 1;
     45     }
     46     return l - first;
     47 }
     48 int query(int l, int r){
     49     int ans = 0;
     50     if (belong[l] == belong[r]){
     51        for (int i = l; i <= r; i++) if (t[i] < l) ans++;
     52     }else {
     53           for (int i = l; i <= block_size * belong[l]; i++) if (t[i] < l) ans++;
     54           for (int i = block_size * (belong[r] - 1) + 1; i <= r; i++) if (t[i] < l) ans++;
     55     }
     56     for (int i = belong[l] + 1; i < belong[r]; i++) ans += find(i, l);
     57     return ans;
     58 }
     59 //处理块
     60 void build(int x){
     61     int l = (x - 1) * block_size + 1, r = min(x * block_size, n);
     62     for (int i = l; i <= r; i++) block[i] = t[i];
     63     sort(block + l, block + r + 1);//对一个块的上一次出现的颜色进行排序 
     64 }
     65 //将x的颜色改变为v
     66 void change(int x, int v){
     67      for (int i = 1; i <= n; i++) last[data[i]] = 0;//暴力重构
     68      data[x] = v;
     69      for (int i = 1; i <= n; i++){
     70          int tmp = t[i];
     71          t[i] = last[data[i]];
     72          if (tmp != t[i]) build(belong[i]);
     73          last[data[i]] = i;
     74      } 
     75 }
     76 
     77 void init(){
     78      scanf("%d%d", &n, &q);
     79      for (int i = 1; i <= n; i++) scanf("%d", &data[i]);
     80      block_size = (int)(sqrt(n * 1.0));
     81      //tot记录总共块的个数 
     82      tot = n / block_size;
     83      if (n % block_size) tot++;
     84      
     85      for (int i = 1; i <= n; i++){
     86          //链表式插入 
     87          t[i] = last[data[i]];
     88          last[data[i]] = i;
     89          belong[i] = (i - 1) / block_size + 1; 
     90      }
     91      for (int i = 1; i <= tot; i++){ build(i);
     92      }
     93 }
     94 void work(){
     95      for (int i = 1; i <= q; i++){
     96          char str[10];
     97          scanf("%s", str);
     98          if (str[0] == 'Q'){
     99             int l, r;
    100             scanf("%d%d", &l, &r);
    101             printf("%d
    ", query(l, r));
    102          }else{
    103             int l, x;
    104             scanf("%d%d", &l, &x);
    105             change(l, x);
    106          }
    107      }
    108 }
    109 
    110 int main(){
    111     
    112     init();
    113     work();
    114     return 0;
    115 }
    View Code
  • 相关阅读:
    mysql修改数据表名
    HDU 5742 It's All In The Mind (贪心)
    HDU 5752 Sqrt Bo (数论)
    HDU 5753 Permutation Bo (推导 or 打表找规律)
    HDU 5762 Teacher Bo (暴力)
    HDU 5754 Life Winner Bo (博弈)
    CodeForces 455C Civilization (并查集+树的直径)
    CodeForces 455B A Lot of Games (博弈论)
    CodeForces 455A Boredom (DP)
    HDU 4861 Couple doubi (数论 or 打表找规律)
  • 原文地址:https://www.cnblogs.com/hoskey/p/4344391.html
Copyright © 2011-2022 走看看