zoukankan      html  css  js  c++  java
  • 莫队算法

    莫队:

    如果你知道了区间l,r的ans。你想知道l-1,r或l,r+1的区间ans,如果你能O(1)转移,就能用莫队在O(n^1.5)(原时间(O(n^2)))解决此为题。(n为个数,m询问数,m和n同级)

    首先,讲解一下它的优化原理。

    原来有m个询问l和r在这m个询问中跑来跑去,对时间很浪费。于是就对这个询问的序列重新排列。

    做法就是:

    • 将n个数分成sqrt(n)块。
    • 按区间排序,以左端点所在块为第一关键字,右端点为第二关键字,进行排序,也就是以(l的分类,r)排列。(来源黄学长的博客

    关于时间复杂度:

    • i与i+1在同一块内,r单调递增,所以r是O(n)的。由于有n^0.5块,所以这一部分时间复杂度是n^1.5。
    • i与i+1跨越一块,r最多变化n,由于有n^0.5块,所以这一部分时间复杂度是n^1.5。
    • i与i+1在同一块内时l变化不超过n^0.5,跨越一块也不会超过n^0.5,忽略*2。由于有m次询问(和n同级),所以时间复杂度是n^1.5。(来源黄学长的博客

    模板(上模板题BZOJ2038):

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<cstdio>
     4 #include<cstring>
     5 #include<cmath>
     6 #include<cstdlib>
     7 #include<vector>
     8 using namespace std;
     9 typedef long long ll;
    10 typedef long double ld;
    11 typedef pair<int,int> pr;
    12 const double pi=acos(-1);
    13 #define rep(i,a,n) for(int i=a;i<=n;i++)
    14 #define per(i,n,a) for(int i=n;i>=a;i--)
    15 #define Rep(i,u) for(int i=head[u];i;i=Next[i])
    16 #define clr(a) memset(a,0,sizeof(a))
    17 #define pb push_back
    18 #define mp make_pair
    19 #define fi first
    20 #define sc second
    21 #define pq priority_queue
    22 #define pqb priority_queue <int, vector<int>, less<int> >
    23 #define pqs priority_queue <int, vector<int>, greater<int> >
    24 #define vec vector
    25 ld eps=1e-9;
    26 ll pp=1000000007;
    27 ll mo(ll a,ll pp){if(a>=0 && a<pp)return a;a%=pp;if(a<0)a+=pp;return a;}
    28 ll powmod(ll a,ll b,ll pp){ll ans=1;for(;b;b>>=1,a=mo(a*a,pp))if(b&1)ans=mo(ans*a,pp);return ans;}
    29 void fre() { freopen("c://test//input.in", "r", stdin); freopen("c://test//output.out", "w", stdout); }
    30 //void add(int x,int y,int z){ v[++e]=y; next[e]=head[x]; head[x]=e; cost[e]=z; }
    31 int dx[5]={0,-1,1,0,0},dy[5]={0,0,0,-1,1};
    32 ll read(){ ll ans=0; char last=' ',ch=getchar();
    33 while(ch<'0' || ch>'9')last=ch,ch=getchar();
    34 while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
    35 if(last=='-')ans=-ans; return ans;
    36 }
    37 int pos[50005],s[50005],c[50005];
    38 ll ans;
    39 inline ll sqr(ll x){
    40     return x*x;
    41 } 
    42 inline ll gcd(ll a,ll b){
    43     return b==0?a:gcd(b,a%b);
    44 }
    45 struct node{
    46     int l,r,id; ll a,b;
    47 }a[50005];
    48 int cmp(node a,node b){
    49     return (pos[a.l]<pos[b.l]||pos[a.l]==pos[b.l]&&a.r<b.r);
    50 }
    51 int cmp_(node a,node b){
    52     return (a.id<b.id);
    53 }
    54 void Update(int x,int v){
    55     ans-=sqr(s[c[x]]); s[c[x]]+=v; ans+=sqr(s[c[x]]);
    56 }
    57 int main()
    58 {
    59     int n=read(),m=read();
    60     for (int i=1;i<=n;i++) c[i]=read();
    61     for (int i=1;i<=m;i++) a[i].l=read(),a[i].r=read(),a[i].id=i;
    62     int block=(int)sqrt(n);
    63     for (int i=1;i<=n;i++)
    64       pos[i]=(i-1)/block+1;
    65     sort(a+1,a+m+1,cmp);
    66     for (int i=1,l=1,r=0;i<=m;i++){
    67         for (;r<a[i].r;r++) Update(r+1,1);
    68         for (;r>a[i].r;r--) Update(r,-1);
    69         for (;l<a[i].l;l++) Update(l,-1);
    70         for (;l>a[i].l;l--) Update(l-1,1);
    71         if (a[i].l==a[i].r){
    72             a[i].a=0; a[i].b=0;
    73             continue;
    74         }
    75         a[i].a=ans-(a[i].r-a[i].l+1);
    76         a[i].b=(ll)(a[i].r-a[i].l+1)*(a[i].r-a[i].l);
    77         ll k=gcd(a[i].a,a[i].b);
    78         a[i].a/=k; a[i].b/=k;
    79     }
    80     sort(a+1,a+m+1,cmp_);
    81     for (int i=1;i<=m;i++){
    82         printf("%lld/%lld
    ",a[i].a,a[i].b);
    83     }
    84     return 0;
    85  } 
    View Code
  • 相关阅读:
    Oracle数据库部分迁至闪存存储方案
    RAC环境下误操作将数据文件添加到本地存储
    Oracle的窗口和自动任务
    ####### Scripts Summary #######
    plsql 操纵表数据的2种方式
    css 如何使图片与文字在div中居中展示?
    eclipse svn新增文件不显示在文件列表,只有修改文件可以提交!
    js 正则表达式校验必须包含字母、数字、特殊字符
    css 禁止录入中文
    POJ 1740:A New Stone Game
  • 原文地址:https://www.cnblogs.com/SXia/p/6776429.html
Copyright © 2011-2022 走看看