zoukankan      html  css  js  c++  java
  • 【HDU4391】【块状链表】Paint The Wall

    Problem Description
    As a amateur artist, Xenocide loves painting the wall. The wall can be considered as a line consisting of n nodes. Each node has its own color.

    Xenocide spends all day in front of the wall. Sometimes, he paints some consecutive nodes so that these nodes have the same color. When he feels tired, he focuses on a particular color and counts the number of nodes that have this color within a given interval.

    Now Xenocide is tired of counting, so he turns to you for help.
     
    Input
    The input consists of several test cases.
    The first line of each test case contains two integer n, m(1<=n, m<=100000) indicating the length of the wall and the number of queries.
    The following line contains N integers which describe the original color of every position.
    Then m lines follow. Each line contains 4 non-negative integers a, l, r, z(1<=a<=2, 0<=l<=r<n ,0<=z<231).
    a = 1 indicates that Xenocide paints nodes between l and r and the resulting color is z.
    a = 2 indicates that Xenocide wants to know how many nodes between l and r have the color z.
     
    Output
    Print the corresponding answer for each queries.
     
    Sample Input
    5 5 1 2 3 4 0 2 1 3 3 1 1 3 1 2 1 3 3 2 0 3 1 2 3 4 1
     
    Sample Output
    1 0 4 1
     
    Source
    【分析】
    块状链表的裸题,同样可以用线段树做。
    记得在map中把不要用的元素要erase掉,不然很占空间,会超。
    晕了,搞了一个半小时,T了无数遍,后面借鉴了别人的代码....,同样是块状链表,差别怎么这么大(╯‵□′)╯︵┻━┻。
      1 #include <iostream>
      2 #include <cstdio>
      3 #include <algorithm>
      4 #include <cstring>
      5 #include <vector>
      6 #include <utility>
      7 #include <iomanip>
      8 #include <string>
      9 #include <cmath>
     10 #include <queue>
     11 #include <assert.h>
     12 #include <map>
     13 
     14 const int N = 100000 + 10;
     15 using namespace std;
     16 int n, c, data[N];
     17 int SIZE;
     18 map<int, int>color[334];
     19 
     20 void change2(int l,int r){
     21     int x = l / SIZE;
     22     if(color[x].size() == 1){//整个块只有一个颜色 
     23         map<int, int>::iterator it = color[x].begin();
     24         int last = it->first, cnt = it->second;
     25         if(c == last) return ;//显然等于原来的颜色就没必要修改了 
     26         if(r - l + 1 == cnt){//整个块都修改 
     27             color[x][c] = r - l + 1;
     28             color[x].erase(it);
     29             return;
     30         }
     31         for(int i = SIZE * x; i < n && i < SIZE * ( x + 1 ); i++){
     32             if(i >= l && i <= r) data[i] = c;
     33             else data[i] = last;
     34         }
     35         color[x][c] = r - l + 1;
     36         color[x][last] = cnt - (r - l + 1);
     37     }else 
     38     for(int i = l; i <= r; i++) {//进行直接修改 
     39         if(data[i] == c) continue;
     40         map<int, int>::iterator it = color[x].find(data[i]);
     41         if(it->second == 1) color[x].erase(it);//记住一定要删除不然会超空间 
     42         else it->second--;
     43         color[x][c]++;
     44         data[i] = c;
     45     }
     46 }
     47 //注意这种带2的操作是在同一个块内操作的 
     48 int query2(int l,int r){
     49     int x = l / SIZE;
     50     if(color[x].count(c)){
     51         if(color[x].size() == 1) return r - l + 1;//整块的颜色唯一 
     52         else{
     53             int cnt = 0;
     54             for(int i = l; i <= r; i++) if(data[i] == c) cnt++;
     55             return cnt;
     56         }
     57     } else return 0;
     58 }
     59 
     60 void change(int l,int r){
     61     int x1 = l / SIZE, x2 = r / SIZE;
     62     if(x1 == x2){change2(l, r);return;}
     63     change2(l, SIZE * (x1 + 1) - 1);
     64     change2(SIZE * x2, r);
     65     //真正无奈 
     66     for(int i = x1 + 1; i < x2; i++){
     67         color[i].clear();
     68         color[i][c] = SIZE;
     69     }
     70 }
     71 
     72 int query(int l,int r){
     73     int x1 = l / SIZE, x2 = r / SIZE;
     74     if(x1 == x2) return query2(l,r);
     75     int Ans = query2(l, SIZE * (x1 + 1) - 1) + query2(SIZE * x2 ,r);
     76     for(int i = x1 + 1;i < x2;i++)
     77     if(color[i].count(c)) Ans += color[i][c];
     78     return Ans;
     79 }
     80 
     81 void init(){
     82     SIZE = (int)sqrt(n * 1.0);
     83     for(int i = 0; i < n; i++) scanf("%d", &data[i]);
     84     for(int i = 0; i <= n / SIZE; i++) color[i].clear();
     85     for(int i = 0; i < n; i++) {
     86         int tmp = i / SIZE;
     87         color[tmp][ data[i] ]++;
     88     }
     89 }
     90 
     91 int main(){
     92     #ifdef LOCAL
     93     freopen("data.txt",  "r",  stdin);
     94     freopen("out.txt",  "w",  stdout); 
     95     #endif
     96     int m;
     97     while(scanf("%d%d",&n,&m) != EOF){         
     98         init();                
     99         for (int i = 1; i <= m; i++){
    100             int t, l, r;
    101             scanf("%d%d%d%d", &t, &l, &r, &c);
    102             if(t == 1) change(l,r);
    103             else printf("%d
    ",query(l,r));
    104         }
    105     }
    106     return 0;
    107 }
    View Code
  • 相关阅读:
    js判断选择时间不能小于当前时间的代码
    shell脚本编程之for语句、if语句使用介绍
    linux命令 chattr超级权限控件
    教你配置linux服务器登陆欢迎信息
    PHP基础入门教程 PHP循环函数
    php获取客户端ip地址
    PHP获取域名、IP地址的方法
    两日期间的间隔
    mysql 案例 ~ pt-archiver 归档工具的使用
    mysql 案例 ~ pt修复工具的使用
  • 原文地址:https://www.cnblogs.com/hoskey/p/4322726.html
Copyright © 2011-2022 走看看