zoukankan      html  css  js  c++  java
  • 分块大法好

    分块的姿势总有问题,找来HZWER的板子;

    BZOJ 3343 1 //bzoj 3343

     2 
     3 
     4 #include<stdio.h>
     5 #include<algorithm>
     6 #include<string.h>
     7 #include<math.h>
     8 #include<string>
     9 #include<iostream>
    10 using namespace std;
    11 typedef long long ll;
    12 
    13 #define N 1000002
    14 
    15 
    16 int a[N],b[N],pos[N],add[N];
    17 int n,Q,block,m;
    18 
    19 
    20 void reset(int x)//对块内排序
    21 {
    22     int l=(x-1)*block+1;
    23     int r=min(block*x,n);
    24     for (int i=l;i<=r;i++) b[i]=a[i];
    25     sort(b+l,b+r+1);
    26 }
    27 
    28 void update(int x,int y,int v)
    29 {
    30     if (pos[x]==pos[y])
    31         for (int i=x;i<=y;i++) a[i]=a[i]+v;
    32     else
    33     {
    34         for (int i=x;i<=pos[x]*block;i++) a[i]=a[i]+v;
    35         for (int i=(pos[y]-1)*block+1;i<=y;i++) a[i]+=v;
    36     }
    37     reset(pos[x]);
    38     reset(pos[y]);
    39     for (int i=pos[x]+1;i<pos[y];i++) add[i]+=v;
    40 }
    41 int find(int x,int v)//在每个块内二分
    42 {
    43     int l=(x-1)*block+1,r=min(x*block,n);
    44     int last=r;
    45     while (l<=r)
    46     {
    47         int mid=(l+r)>>1;
    48         if (b[mid]<v) l=mid+1;
    49         else r=mid-1;
    50     }
    51     return last-l+1;
    52 }
    53 
    54 int query(int x,int y,int v)
    55 {
    56     int sum=0;
    57     if (pos[x]==pos[y])//在一个块内
    58     {
    59         for (int i=x;i<=y;i++)
    60         if (a[i]+add[pos[i]]>=v) sum++;
    61     }
    62     else//暴力处理两端
    63     {
    64         for (int i=x;i<=pos[x]*block;i++)
    65           if (a[i]+add[pos[i]]>=v) sum++;
    66         for (int i=(pos[y]-1)*block+1;i<=y;i++)
    67          if (a[i]+add[pos[i]]>=v) sum++;
    68     }
    69     for (int i=pos[x]+1;i<pos[y];i++)//对每个块二分
    70         sum+=find(i,v-add[i]);
    71     return sum;
    72 }
    73 
    74 int main()
    75 {
    76     scanf("%d%d",&n,&Q);
    77     block=sqrt(n);//每块有多少
    78     for (int i=1;i<=n;i++)
    79     {
    80         scanf("%d",&a[i]);
    81         pos[i]=(i-1)/block+1;//处于哪个块
    82     }
    83     if (n%block) m=n/block+1;
    84     else m=n/block;
    85     for (int i=1;i<=m;i++) reset(i);
    86     while (Q--)
    87     {
    88         char s[4];
    89         int x,y,v;
    90         scanf("%s%d%d%d",s,&x,&y,&v);
    91         if (s[0]=='M') update(x,y,v);
    92         else printf("%d ",query(x,y,v));
    93     }
    94     return 0;
    95 }

     BZOJ 2120:

     求区间不同数的种类,并且修改单点值。

    修改操作小于1000,记录每一个颜色其前一位置。

    然后分块,在同一块中每一pre排好顺序,二分其位置,得到答案。

    修改暴力即可View Code 

  • 相关阅读:
    C#动态执行代码
    C#的动态编译执行
    Win7/Vista激活后添加grub引导Linux最简单方法!无需命令行!
    乔布斯:关于 Flash 的思考
    I want to live in a honest country
    twitter bbs
    my follow rule on twitter
    blog will be repleace by twitter?
    blog Prediction
    也说说对blog是否需要静态页面的一点看法
  • 原文地址:https://www.cnblogs.com/forgot93/p/4781352.html
Copyright © 2011-2022 走看看