poj 2299(离散化+树状数组)
2015-11-04 00:21
447 查看
区域赛的打击好大。。。直接就是铁了。
就是自己不努力的结果
好浮躁
还是要沉下心来做好一件事
算法是核心的东西。
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
这个题就是求逆序数的对数,就是前一个数比后一个数大
怎么用树状数组呢?就是比如 9 6 5 11 3,先将1插入9的位置,然后i-sun(a[9]),是0,i是插入的第几个数,a数组是树状数组的那个数组,然后1插入位置6,这时候是2-sum(a[6]),发现是1,所以就是有一对了,这个意思很明显,就是看前面有几个数插入到了这个数的前面,有几个就有几个正序的数对呗。
然后是离散化,刚才的例子能看出来,数组开到了11,如果一个数更大一点,极端一点,会很大很大,不如将这五个数分别用4 3 2 5 1代替,只是表示他们的大小关系而不关心他们的值,用sort排序就好,嘿嘿~
当然了树状数组要熟练!
#include <iostream>
#include <cstdio>
#include <string.h>
#include <algorithm>
using namespace std;
int aa[500001];
struct node
{
int val,xu;
int xinxu;
}a[500001];
bool cmp(node a,node b)
{
return a.val<b.val;
}
bool cmp1(node a,node b)
{
return a.xu<b.xu;
}
int n;
int lowbit(int x)
{
return x&-x;
}
void add(int x,int val)
{
while(x<=n)
{
aa[x]+=val;
x+=lowbit(x);
}
}
int sum(int x)
{
int s = 0;
while(x>0)
{
s+=aa[x];
x-=lowbit(x);
}
return s;
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
memset(aa,0,sizeof(aa));
if(n==0) break;
int i,j;
for(i = 1;i<=n;i++)
{
scanf("%d",&a[i].val);
a[i].xu = i;
//a[i].xinxu = 0;
}
sort(a+1,a+n+1,cmp);
//for(i = 1;i<=n;i++) printf("* %d\n ",a[i].xu);
for(i = 1;i<=n;i++) a[i].xinxu=i;
sort(a+1,a+n+1,cmp1); //两次sort明显慢了。。。。可以不用的
//for(i=1;i<=n;i++) printf("& %d\n",a[i].xinxu);
//for(i=1;i<=n;i++) printf(" %d\n",a[i].val);
long long summm = 0;
for(i = 1;i <=n;i++)
{
add(a[i].xinxu,1);
summm+=i-sum(a[i].xinxu);
}
printf("%lld\n",summm);
}
return 0;
}
时间少一点的代码:
#include <iostream>
#include <cstdio>
#include <string.h>
#include <algorithm>
using namespace std;
int a[500001],b[500001];
int n;
struct node
{
int val,xu;
}c[500001];
bool cmp(node a,node b)
{
return a.val<b.val;
}
int lowbit(int x)
{
return x&-x;
}
void add(int x,int val)
{
while(x<=n)
{
a[x]+=val;
x+=lowbit(x);
}
}
int sum(int x)
{
int s=0;
while(x>0)
{
s+=a[x];
x-=lowbit(x);
}
return s;
}
int main()
{
int i;
while(scanf("%d",&n)==1&&n)
{
memset(a,0,sizeof(a));
for(i=1;i<=n;i++)
{
scanf("%d",&c[i].val);
c[i].xu=i;
}
sort(c+1,c+n+1,cmp);
for(i=1;i<=n;i++)
{
b[c[i].xu]=i;
}
long long int summ = 0;
for(i=1;i<=n;i++)
{
add(b[i],1);
summ+=i-sum(b[i]);
}
printf("%lld\n",summ);
}
return 0;
}
就是自己不努力的结果
好浮躁
还是要沉下心来做好一件事
算法是核心的东西。
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
这个题就是求逆序数的对数,就是前一个数比后一个数大
怎么用树状数组呢?就是比如 9 6 5 11 3,先将1插入9的位置,然后i-sun(a[9]),是0,i是插入的第几个数,a数组是树状数组的那个数组,然后1插入位置6,这时候是2-sum(a[6]),发现是1,所以就是有一对了,这个意思很明显,就是看前面有几个数插入到了这个数的前面,有几个就有几个正序的数对呗。
然后是离散化,刚才的例子能看出来,数组开到了11,如果一个数更大一点,极端一点,会很大很大,不如将这五个数分别用4 3 2 5 1代替,只是表示他们的大小关系而不关心他们的值,用sort排序就好,嘿嘿~
当然了树状数组要熟练!
#include <iostream>
#include <cstdio>
#include <string.h>
#include <algorithm>
using namespace std;
int aa[500001];
struct node
{
int val,xu;
int xinxu;
}a[500001];
bool cmp(node a,node b)
{
return a.val<b.val;
}
bool cmp1(node a,node b)
{
return a.xu<b.xu;
}
int n;
int lowbit(int x)
{
return x&-x;
}
void add(int x,int val)
{
while(x<=n)
{
aa[x]+=val;
x+=lowbit(x);
}
}
int sum(int x)
{
int s = 0;
while(x>0)
{
s+=aa[x];
x-=lowbit(x);
}
return s;
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
memset(aa,0,sizeof(aa));
if(n==0) break;
int i,j;
for(i = 1;i<=n;i++)
{
scanf("%d",&a[i].val);
a[i].xu = i;
//a[i].xinxu = 0;
}
sort(a+1,a+n+1,cmp);
//for(i = 1;i<=n;i++) printf("* %d\n ",a[i].xu);
for(i = 1;i<=n;i++) a[i].xinxu=i;
sort(a+1,a+n+1,cmp1); //两次sort明显慢了。。。。可以不用的
//for(i=1;i<=n;i++) printf("& %d\n",a[i].xinxu);
//for(i=1;i<=n;i++) printf(" %d\n",a[i].val);
long long summm = 0;
for(i = 1;i <=n;i++)
{
add(a[i].xinxu,1);
summm+=i-sum(a[i].xinxu);
}
printf("%lld\n",summm);
}
return 0;
}
时间少一点的代码:
#include <iostream>
#include <cstdio>
#include <string.h>
#include <algorithm>
using namespace std;
int a[500001],b[500001];
int n;
struct node
{
int val,xu;
}c[500001];
bool cmp(node a,node b)
{
return a.val<b.val;
}
int lowbit(int x)
{
return x&-x;
}
void add(int x,int val)
{
while(x<=n)
{
a[x]+=val;
x+=lowbit(x);
}
}
int sum(int x)
{
int s=0;
while(x>0)
{
s+=a[x];
x-=lowbit(x);
}
return s;
}
int main()
{
int i;
while(scanf("%d",&n)==1&&n)
{
memset(a,0,sizeof(a));
for(i=1;i<=n;i++)
{
scanf("%d",&c[i].val);
c[i].xu=i;
}
sort(c+1,c+n+1,cmp);
for(i=1;i<=n;i++)
{
b[c[i].xu]=i;
}
long long int summ = 0;
for(i=1;i<=n;i++)
{
add(b[i],1);
summ+=i-sum(b[i]);
}
printf("%lld\n",summ);
}
return 0;
}
相关文章推荐
- UESTC 1217(树状数组+离散化)
- redis 安装与配置
- ubuntu上安装配置mysql
- 为初次使用linux设置 root密码
- spark sql DataFrame操作
- 对字符串中的字符进行统计
- css布局的学习笔记
- 实现 strcmp
- nodejs express 静态文件的路径
- nginx performance monitor
- 八,游戏世界的渲染
- “ML学分计划”说明书
- 项目冲刺随笔汇总
- linux进程管理与作业控制
- 在PowerDesigner的PDM图形窗口中显示数据列的中文注释
- 实现 strcat
- JVM 默认Xss大小
- 七,游戏世界
- su - root 与su root的区别
- 2013 Aizu Regional Contest(UValive 6661,6662,6663,6664,6665,6669)