zoukankan      html  css  js  c++  java
  • 分块 && 洛谷 P2801 教主的魔法

    传送门


    分块大法好

    分块

    • 什么是分块

    • 就是把一连串的东西分成几个部分,通常是分成√n个部分,每个部分√n个数字,然后每一块分开处理。(当然有别的情况)
    • 有什么用

    • 时间得到了优化,把n变成了sqrt(n)*log(sqrt(n))。这是一种优雅的暴力呢
    • 主要思路?
    • 每一块内按照权值排序。对于每一次操作的区间,若是中间完整的块,就用lazy处理,若是两边的不完整的块,就先按id排序,然后暴力处理,再按照value排序回去。完整的块每次操作O(1),最多有sqrt(n)块,总共sqrt(n);两遍的块每次操作sqrt(n)*log(sqrt(n)),最多有两块,总共是sqrt(n)*log(sqrt(n))。所以最后的一次操作时间复杂度为O(sqrt(n)*log(sqrt(n)))

    解题思路

    看一下这个题,就是个板子,但是有些需要注意的事情:

    1. 判断区间两个端点是否在同一个块里,防止重复加或者重复计算。
    2. lower_bound因为是在结构体里查询,所以需要把查询的值包装成一个结构体,然后用上比较函数。
    3. 求块的个数以及大小时一定要sq=sqrt(n)+1,不要吝啬,即使多一个块也不能漏掉元素!!
    4. 要注意到零散块的边界

    AC代码

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<cmath>
     4 using namespace std;
     5 const int maxn=1000005;
     6 struct node{
     7     int value,id;
     8 }a[maxn];
     9 int n,q,cnt,num,ans,l[maxn],r[maxn],id[maxn],sq,lazy[maxn]; 
    10 bool cmp_value(node a,node b){
    11     if(a.value==b.value) return a.id<b.id;
    12     return a.value<b.value;
    13 }
    14 bool cmp_id(node a,node b){
    15     return a.id<b.id;
    16 }
    17 inline void add(int ll,int rr,int w){
    18     sort(a+l[id[ll]],a+r[id[ll]]+1,cmp_id);
    19     for(int i=ll;i<=rr;i++) a[i].value+=w;
    20     sort(a+l[id[ll]],a+r[id[ll]]+1,cmp_value);
    21 }
    22 inline int query(int ll,int rr,int w){
    23     int res=0;
    24     sort(a+l[id[ll]],a+r[id[ll]]+1,cmp_id);
    25     for(int i=ll;i<=rr;i++) if(a[i].value>=w) res++;
    26     sort(a+l[id[ll]],a+r[id[ll]]+1,cmp_value);
    27     return res;
    28 }
    29 int main()
    30 {
    31     cin>>n>>q;
    32     for(int i=1;i<=n;i++){
    33         cin>>a[i].value;
    34         a[i].id=i;
    35     }
    36     sq=sqrt(n)+1;
    37     int now=1;
    38     for(int i=1;i<=n;i++){
    39         if(cnt==sq){
    40             sort(a+l[now],a+i,cmp_value);
    41             cnt=0;
    42             r[now++]=i-1;
    43             l[now]=i;
    44         }
    45         cnt++;
    46         id[i]=now;
    47     }
    48     r[now]=n;
    49     for(int i=1;i<=q;i++){
    50         char c;
    51         int ll,rr,w;
    52         cin>>c>>ll>>rr>>w;
    53         if(c=='M'){
    54             for(int i=id[ll]+1;i<=id[rr]-1;i++) lazy[i]+=w;
    55             add(ll,min(rr,r[id[ll]]),w);
    56             if(id[ll]!=id[rr]) add(l[id[rr]],rr,w);
    57         }else{
    58             ans=0;
    59             node x;
    60             x.id=0;
    61             for(int i=id[ll]+1;i<=id[rr]-1;i++) x.value=w-lazy[i],ans+=a+r[i]-lower_bound(a+l[i],a+r[i]+1,x,cmp_value)+1;
    62             ans+=query(ll,min(rr,r[id[ll]]),w-lazy[id[ll]]);
    63             if(id[ll]!=id[rr]) ans+=query(l[id[rr]],rr,w-lazy[id[rr]]);
    64             cout<<ans<<endl;
    65         }
    66     }
    67     return 0;
    68 }
  • 相关阅读:
    第十八课 顺序存储线性表的分析
    第十七课 StaticList和DynamicList实现
    第十六课 顺序存储结构的抽象实现
    第十五课 线性表的顺序存储结构
    第十四课 线性表的本质和操作
    第十三课 类族结构的进化
    第十二课 顶层父类的创建
    第十一课 异常类构建
    HDU 5773The All-purpose Zero
    HDU 5755 Gambler Bo
  • 原文地址:https://www.cnblogs.com/yinyuqin/p/14371139.html
Copyright © 2011-2022 走看看