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
  • 相关阅读:
    游标
    js问题杂记
    博客园页面设置
    Natas13 Writeup(文件上传,绕过图片签名检测)
    Natas12 Writeup(文件上传漏洞)
    Natas11 Writeup(常见编码、异或逆推、修改cookie)
    Natas10 Writeup(正则表达式、grep命令)
    Natas9 Writeup(命令注入)
    Natas8 Writeup(常见编码、php函数)
    Natas7 Writeup(任意文件读取漏洞)
  • 原文地址:https://www.cnblogs.com/hoskey/p/4344391.html
Copyright © 2011-2022 走看看