bzoj2141排队(辣鸡但是好写的方法)
题意很明确,也非常经典:
一个支持查询 区间中比k大的数的个数 并且支持单点修改的序列
——因为题意可以转化为:查询这两个数中比后者大的个数、比后者小的个数、比前者大的个数、比前者小的个数(根据这4个就能算出增加/减少了多少对逆序对)并且把两个数修改掉
于是就出现了
——来自百度
一个二分就能解决套个卵蛋woc身为一个蒟蒻,表示没有一个写得出的
于是我就想了一个好写(Rank100+几乎T掉)的方法:
首先复制一份原数据,把一份分块,并且保证每一块中的单调(也就是调用sqrt(n)次排序)
然后在查询时对于单块暴力处理,对于整块二分查找;修改时冒泡(呵呵,不要吐槽)
——一听复杂度就好大,那就算一算吧
首先要排序O(sqrt(n)*sqrt(n)*lg sqrt(n)) //sqrt(n)次的排序,每次nlgn(这里的n为原题的sqrt(n))
其次是查询O(m*(sqrt(n)+sqrt(n)*lg sqrt(n))) //总共有m次,每次零散的有sqrt(n)个,整块的有sqrt(n)块,每块费时lg sqrt(n)
最后是修改O(m*(sqrt(n)+sqrt(n))) //冒个泡应该不用解释,每次收尾都需要冒一遍,一遍最多sqrt(n)次移动
然后愉快地堆起来变成预处理O(n*lg sqrt(n))主体O(m*sqrt(n)*lgn)
介于数据弱(如果按套来套去的结构算好像还可以加大一点数据,但是蒟蒻表示受不了,这么个简单思路我调了一下午),我还是过掉了
代码风格属于臭婆娘的擦脚布,不喜勿喷
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;
int n,m,x,y,N;
int a[],b[];//未排序数据和已排序数据
int l[],r[];//分块两端
//处理重复数据真TM的累,find和Find带_的是找小于给定关键字的数的个数的,不带的是找大于的个数的
int Find(int o,int x)//在一块中二分查找x
{
int L=l[o],R=r[o];
while(L<R-)
{
int mid=(L+R)/;
if(b[mid]<=x)//这边一开始缺个等号导致我调一下午
L=mid;
else
R=mid;
}
if(b[R]<=x)
return r[o]-R;
else
if(x<b[L])
return r[o]-L+;
else
return r[o]-L;
}
int find(int x,int y,int z)//查询,分成三段分别求解
{
int sum=;
for(int i=;i<=N;i++)
if((x<=l[i])&&(r[i]<=y))
sum+=Find(i,z);
else
if((x>=l[i])&&(y<=r[i]))
{
for(int j=x;j<=y;j++)
sum+=a[j]>z;
return sum;
}
else
if(x>=l[i] && x<=r[i])
for(int j=x;j<=r[i];j++)
sum+=a[j]>z;
else
if(l[i]<=y && y<=r[i])
{
for(int j=l[i];j<=y;j++)
sum+=a[j]>z;
return sum;
}
return sum;
}
int _Find(int o,int x)//在一块中二分查找x
{
int L=l[o],R=r[o];
while(L<R-)
{
int mid=(L+R)/;
if(b[mid]<x)//这边不能有等号,非常神奇,建议想一想为什么
L=mid;
else
R=mid;
}
if(b[R]<x)
return R-l[o]+;
else
if(x<=b[L])
return L-l[o];
else
return R-l[o];
}
int _find(int x,int y,int z)//查询,分成三段分别求解
{
int sum=;
for(int i=;i<=N;i++)
if((x<=l[i])&&(r[i]<=y))
sum+=_Find(i,z);
else
if((x>=l[i])&&(y<=r[i]))
{
for(int j=x;j<=y;j++)
sum+=a[j]<z;
return sum;
}
else
if(x>=l[i] && x<=r[i])
for(int j=x;j<=r[i];j++)
sum+=a[j]<z;
else
if(l[i]<=y && y<=r[i])
{
for(int j=l[i];j<=y;j++)
sum+=a[j]<z;
return sum;
}
return sum;
}
void change(int x,int y)//把位于x的数改成y,冒个泡
{
int i,j;
for(i=;r[i]<x;i++);
for(j=l[i];b[j]!=a[x];j++);
b[j]=y;
while((j<r[i])&&(b[j]>b[j+]))
{
swap(b[j],b[j+]);
j++;
}
while((j>l[i])&&(b[j]<b[j-]))
{
swap(b[j],b[j-]);
j--;
}
a[x]=y;
}
int init()//预处理,分块+排序
{
int sq=(int)sqrt(n);
for(int i=;i<=sq;i++)
{
l[i]=sq*(i-)+;
r[i]=sq*i;
}
if(sq*sq<n)
{
l[sq+]=sq*sq+;
r[++sq]=n;
}
memcpy(b,a,sizeof(a));
for(int i=;i<=sq;i++)
sort(b+l[i],b+r[i]+);
return sq;
}
int main()
{
scanf("%d",&n);
for(int i=;i<=n;i++)
scanf("%d",&a[i]);
N=init();
int ans=;
for(int i=;i<n;i++)
ans+=_find(i+,n,a[i]);
printf("%d\n",ans);
scanf("%d",&m);
for(int i=;i<=m;i++)
{
scanf("%d%d",&x,&y);
if(x>y)
swap(x,y);
ans-=find(x,y-,a[y]);
ans+=_find(x,y-,a[y]);
if(y-x>)
{
ans+=find(x+,y-,a[x]);
ans-=_find(x+,y-,a[x]);
}
printf("%d\n",ans);
int t=a[x];
change(x,a[y]);
change(y,t);
}
return ;
}
据说一个函数不能太长,否则难看,于是就瞎写成了这副德行%还是不习惯啊
bzoj2141排队(辣鸡但是好写的方法)的更多相关文章
- 7.29 NOIP模拟测试10 辣鸡(ljh)+模板(ac)+大佬(kat)
T1 辣鸡(ljh) 就是一道分类讨论的暴搜,外加一丢丢的减枝,然而我挂了,为啥呢,分类讨论变量名打错,大于小于号打反,能对才怪,写了sort为了调试就注释了,后来忘了解开,小减枝也没打.但是这道题做 ...
- JVM 辣鸡回收
垃圾回收算法 标记清除法 先标记出需要回收的对象,然后一次性回收.缺点:会产生内存碎片,并且效率也不高. 标记压缩法 先标记出需要回收的对象,然后让存活对象向一端移动,移动的过程中进行回收辣鸡.避免了 ...
- [CSP-S模拟测试]:辣鸡(ljh) (暴力)
题目描述 辣鸡$ljh\ NOI$之后就退役了,然后就滚去学文化课了.然而在上化学课的时候,数学和化学都不好的$ljh$却被一道简单题难住了,受到了大佬的嘲笑.题目描述是这样的:在一个二维平面上有一层 ...
- noip模拟6[辣鸡·模板·大佬·宝藏]
这怕不是学长出的题吧 这题就很迷 这第一题吧,正解竟然是O(n2)的,我这是快气死了,考场上一直觉得aaaaa n2过不了过不了, 我就去枚举边了,然后调了两个小时,愣是没调出来,然后交了个暴力,就走 ...
- NOIP模拟测试10「大佬·辣鸡·模板」
大佬 显然假期望 我奇思妙想出了一个式子$f[i]=f[i-1]+\sum\limits_{j=1}^{j<=m} C_{k \times j}^{k}\times w[j]$ 然后一想不对得容 ...
- [改善Java代码]不推荐覆写start方法
多线程比较简单的方式是继承Thread类,然后覆写run()方法,在客户端程序中通过调用对象的start方法即可启动一个线程,这个是多线程程序的标准写法. 错误代码: public class Cli ...
- [改善Java代码]覆写equals方法必须覆写hashCode方法
覆写equals方法必须覆写hashCode方法,这条规则基本上每个Javaer都知道,这也是JDK API上反复说明的,不过为什么要这样做呢?这两个方法之间有什么关系呢?本建议就来解释该问题,我们先 ...
- [改善Java代码]覆写equals方法时不要识别不出自己
建议45: 覆写equals方法时不要识别不出自己 我们在写一个JavaBean时,经常会覆写equals方法,其目的是根据业务规则判断两个对象是否相等,比如我们写一个Person类,然后根据姓名判断 ...
- [改善Java代码]推荐覆写toString方法
建议49: 推荐覆写toString方法 为什么要覆写toString方法,这个问题很简单,因为Java提供的默认toString方法不友好,打印出来看不懂,不覆写不行,看这样一段代码: public ...
随机推荐
- LoadRunner 获取接口请求响应信息
Action() { int nHttpRetCode; // 默认最大长度为256,get请求需注意缓存问题,需要根据content-length进行修改 web_set_max_html_para ...
- [Unity] Cg标准函数库
- oracle创建用户
--首先用管理员的帐户登录(要有修改用户的权限)system,默认数据库orcl. CREATE USER lcs IDENTIFIED BY lcs default tablespace lics_ ...
- (zz)linux awk
博文转载自http://www.cnblogs.com/ggjucheng/archive/2013/01/13/2858470.html 谢谢原作者.条理很清楚,由浅入深.敲了每一行命令,正确无误. ...
- C和指针 第五章 习题
下列输出的值: #include <stdio.h> int func(){ static int count = 1; return ++count; } int main() { in ...
- UVA2322
题目:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_pr ...
- BZOJ2007——[Noi2010]海拔
1.题意:一个裸的最小割 2.分析:直接转成对偶图最短路就好了,水爆了!(雾) #include <queue> #include <cstdio> #include < ...
- 页面localStorage用作数据缓存的简易封装
最近做了一些前端控件的封装,需要用到数据本地存储,开始采用cookie,发现很容易就超过了cookie的容量限制,于是改用localStorage,但localStorage过于简单,没有任何管理和限 ...
- Ackerman函数的栈实现
一.Ackerman函数: ackerman函数的定义如下: 二.Ackerman函数的递归实现: 利用递归来实现ackerman函数是比较简单的: /*Sample Input: 0 1 1 1 S ...
- table的border重合问题
1. table { border-collapse: collapse; } td { border: 1px solid blue; } 用css的方法直接实现 2. border="1 ...