【莫队算法】bzoj3289 Mato的文件管理

莫队算法,离线回答询问,按一定大小(sqrt(n*log(n))左右)将答案分块,按 ①左端点所在块②右端点 双关键字排序。

然后暴力转移。

转移的时候用树状数组。

O(n*sqrt(n)*log(n))。

注意:①在一列数的后面添加一个数,逆序对数会增加 数列中比它大的数的个数。

②在一列数的后面删除一个数,逆序对数会减少 数列中比它大的数的个数。

③在一列数的前面添加一个数,逆序对数会增加 数列中比它小的数的个数。

④在一列数的前面删除一个数,逆序对数会减少 数列中比它小的数的个数。

  1 #include<cstdio>
  2 #include<algorithm>
  3 #include<cmath>
  4 using namespace std;
  5 struct Point{int x,y;}a[50001];
  6 struct ASK{int l,r,lb,p;}Q[50001];
  7 bool operator < (const ASK &a,const ASK &b){return a.lb!=b.lb ? a.lb<b.lb : a.r<b.r;}
  8 bool operator < (const Point &a,const Point &b){return a.x<b.x;}
  9 int n,m,sz,sum,num[50001],b[50001],cnt;
 10 int d[50001],ans[50001],res;
 11 inline int lowbit(const int &x){return x&(-x);}
 12 inline void add(int p,const int &x){while(p<=n){d[p]+=x;p+=lowbit(p);}}
 13 inline int getsum(int p){int res=0;while(p){res+=d[p];p-=lowbit(p);}return res;}
 14 int Res,Num;char C,CH[12];
 15 inline int G()
 16 {
 17     Res=0;C=‘*‘;
 18     while(C<‘0‘||C>‘9‘)C=getchar();
 19     while(C>=‘0‘&&C<=‘9‘){Res=Res*10+(C-‘0‘);C=getchar();}
 20     return Res;
 21 }
 22 inline void P(long long x)
 23 {
 24     Num=0;if(!x){putchar(‘0‘);puts("");return;}
 25     while(x>0)CH[++Num]=x%10,x/=10;
 26     while(Num)putchar(CH[Num--]+48);
 27     puts("");
 28 }
 29 void makeblock()
 30 {
 31     sz=sqrt((double)n*4.6); int L,R;
 32     for(sum=1;sum*sz<n;sum++)
 33       {
 34         L=(sum-1)*sz+1; R=sum*sz;
 35         for(int i=L;i<=R;i++) num[i]=sum;
 36       }
 37     L=sz*(sum-1)+1; R=n;
 38     for(int i=L;i<=R;i++) num[i]=sum;
 39 }
 40 void LiSan()
 41 {
 42     int en=1; sort(a+1,a+n+1); b[a[1].y]=1;
 43     for(int i=2;i<=n;i++)
 44       {
 45         if(a[i].x!=a[i-1].x) en++;
 46         b[a[i].y]=en;
 47       }
 48 }
 49 int main()
 50 {
 51     n=G();
 52     for(int i=1;i<=n;i++)
 53       {
 54         a[i].x=G();
 55         a[i].y=i;
 56       }
 57     makeblock(); LiSan(); m=G();
 58     for(int i=1;i<=m;i++)
 59       {
 60         Q[i].l=G(); Q[i].r=G();
 61         Q[i].lb=num[Q[i].l];
 62         Q[i].p=i;
 63       }
 64     sort(Q+1,Q+m+1);
 65     for(int i=Q[1].l;i<=Q[1].r;i++)
 66       {
 67         cnt++;
 68         add(b[i],1);
 69         res+=(cnt-getsum(b[i]));
 70       } ans[Q[1].p]=res;
 71     for(int i=2;i<=m;i++)
 72       {
 73         if(Q[i].l<Q[i-1].l)
 74           {
 75             for(int j=Q[i-1].l-1;j>=Q[i].l;j--)
 76               {
 77                 res+=getsum(b[j]-1);
 78                 add(b[j],1);
 79               }
 80             cnt+=(Q[i-1].l-Q[i].l);
 81           }
 82         else
 83           {
 84             for(int j=Q[i-1].l;j<Q[i].l;j++)
 85               {
 86                 res-=getsum(b[j]-1);
 87                 add(b[j],-1);
 88               }
 89             cnt-=(Q[i].l-Q[i-1].l);
 90           }
 91         if(Q[i].r<Q[i-1].r)
 92           {
 93             for(int j=Q[i-1].r;j>Q[i].r;j--)
 94               {
 95                 res-=(cnt-getsum(b[j]));
 96                 cnt--;
 97                 add(b[j],-1);
 98               }
 99           }
100         else
101           {
102             for(int j=Q[i-1].r+1;j<=Q[i].r;j++)
103               {
104                 cnt++;
105                 add(b[j],1);
106                 res+=(cnt-getsum(b[j]));
107               }
108           }
109         ans[Q[i].p]=res;
110       }
111     for(int i=1;i<=m;i++) P(ans[i]);
112     return 0;
113 }
时间: 2024-08-04 03:06:20

【莫队算法】bzoj3289 Mato的文件管理的相关文章

【BZOJ3289】Mato的文件管理 莫队算法+树状数组

[BZOJ3289]Mato的文件管理 Description Mato同学从各路神犇以各种方式(你们懂的)收集了许多资料,这些资料一共有n份,每份有一个大小和一个编号.为了防止他人偷拷,这些资料都是加密过的,只能用Mato自己写的程序才能访问.Mato每天随机选一个区间[l,r],他今天就看编号在此区间内的这些资料.Mato有一个习惯,他总是从文件大小从小到大看资料.他先把要看的文件按编号顺序依次拷贝出来,再用他写的排序程序给文件大小排序.排序程序可以在1单位时间内交换2个相邻的文件(因为加密

【bzoj3289】Mato的文件管理 离散化+莫队算法+树状数组

原文地址:http://www.cnblogs.com/GXZlegend/p/6805224.html 题目描述 Mato同学从各路神犇以各种方式(你们懂的)收集了许多资料,这些资料一共有n份,每份有一个大小和一个编号.为了防止他人偷拷,这些资料都是加密过的,只能用Mato自己写的程序才能访问.Mato每天随机选一个区间[l,r],他今天就看编号在此区间内的这些资料.Mato有一个习惯,他总是从文件大小从小到大看资料.他先把要看的文件按编号顺序依次拷贝出来,再用他写的排序程序给文件大小排序.排

BZOJ 3289:Mato的文件管理(莫队算法+树状数组)

http://www.lydsy.com/JudgeOnline/problem.php?id=3289 题意:…… 思路:求交换次数即求逆序对数.确定了这个之后,先离散化数组.然后在后面插入元素的话,就是在区间里面找比它大的元素数量,在前面插入元素的话,就是在区间里面找比它小的元素数量.删除操作类似.因为排序是从小到大排序,所以要找比它大的数量就是区间长度减去小于等于该元素的数量,所以是(R - L + 1 - sum(a[i])),要找比它小的数量就是(sum(a[i] - 1)).然后用莫

莫队算法小结(Markdown版)

wtf,最近挖坑有点小多啊,没办法>_<容我先把糖果公园A了再来写这个吧= =看看今天能不能A掉 好吧,我承认我第二天才把糖果公园A掉>_<下面把这篇小结补上 首先众所周知的是莫队算法是要把询问先按左端点属于的块排序,再按右端点排序 复杂度就先不证了,有兴趣的同学可以自己YY下或者查阅资料 下面举几个例子详细说明 1.小Z的袜子 Description: 给定一个序列m个询问 每次询问: 区间中选两个数,两个数相等的概率 若概率为0则输出01 仔细观察发现,令x表示x这个值出现的次

莫队算法小结

唔,想有更加舒爽的阅读体验请移步http://mlz000.logdown.com/posts/252433-mo-algorithm-summary 首先众所周知的是莫队算法是要把询问先按左端点属于的块排序,再按右端点排序 复杂度就先不证了,有兴趣的同学可以自己YY下或者查阅资料 下面举几个例子详细说明 1.小Z的袜子 Description: 给定一个序列m询问 每次询问: 区间中选两个数,两个数相等的概率 若概率为则输出0/1 仔细观察发现,令x表示x个值出现的次数,则每次询问[l,r]区

数据离散化 ( 以及 stl 中的 unique( ) 的用法 )+ bzoj3289:Mato的文件管理

http://blog.csdn.net/gokou_ruri/article/details/7723378 ↑惯例Mark大神的博客 bzoj3289:Mato的文件管理 线段树求逆序对+莫队,但是数据量50000却没有给出范围,既然求逆序对,那么我们关注的只是数据之间的相对大小,此时我们可以把这50000个数据进行简化...嗯看大神的博客就明白了不需要多解释什么了..   下面是博客中未授权截取的大神的代码板子....不过都是自己看应该也没什么吧..... sort(sub_a,sub_a

莫队算法

Beautiful Girl 题意 给定一个长度为 n 的序列 a[1], a[2], ..., a[n] . m 组询问 (l, r, K) , 求区间 [l, r] 去除重复的数之后的第 K 小. n, m <= 100000 . 分析 莫队算法 + 值域分块. 1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <cctype> 5 #include &

BZOJ4241 历史研究 莫队算法 堆

欢迎访问~原文出处--博客园-zhouzhendong&AK 去博客园看该题解 题目 Description IOI国历史研究的第一人--JOI教授,最近获得了一份被认为是古代IOI国的住民写下的日记.JOI教授为了通过这份日记来研究古代IOI国的生活,开始着手调查日记中记载的事件. 日记中记录了连续N天发生的时间,大约每天发生一件. 事件有种类之分.第i天(1<=i<=N)发生的事件的种类用一个整数Xi表示,Xi越大,事件的规模就越大. JOI教授决定用如下的方法分析这些日记: 1.

CodeForces - 86D 莫队算法

http://codeforces.com/problemset/problem/86/D 莫队算法就是调整查询的顺序,然后暴力求解. 每回可以通过现有区间解ans(l,r)得到区间(l+1,r),(l-1,r),(l,r+1),(l,r-1)的区间解. 调整方式http://blog.csdn.net/bossup/article/details/39236275 这题比那个还要简单,查询的是K^2*Z,很清楚就是莫队算法,然而做的时候没有学过,回来补题补到 关键是我一直没明白为什么重载小于号