HDU-5792-World is Exploding-树状数组
2016-08-06 21:23
387 查看
题意:求一个n个数字的序列A
其中a,b,c,d两两互不相等,1<=a<b<=n ,1<=c<d<=n A[a]<A[b] A[c]>A[d] 其中a,b,c,d的组数
思路:先算一个总的数量=逆序对乘顺序对。然后再减去重复,发现只有a=c a=d b=c b=d
然后用树状数组维护,首先要离散化。
ls[i],lb[i],rs[i],rb[i]分别表示左边比当前位置小的,左边比当前位置大的,右边比当前位置小的,右边比当前位置大的。
逆序对数=sigma(lb[i])
顺序对数=sigma(ls[i])
.其他的四项画了草图可得,分别为:
rs[i]*rb[i] //a=c
lb[i]*rb[i] //a=d
ls[i]*rs[i] //b=c
ls[i]*lb[i] //b=d
#include<bits/stdc++.h>
#define maxn 55555
using namespace std;
int n;
int c[maxn];
int b[maxn];
int ls[maxn],lb[maxn],rs[maxn],rb[maxn];
///左边比自己小的,左边比自己大的,右边比自己小的,右边比自己大的
struct NODE{
int v,num;
}a[maxn];
int v[maxn];
bool cmp(const NODE X,const NODE Y) {
return X.v<Y.v;
}
int lowbit(int x) {
return x&-x;
}
/**单点修改区间求和**/
/**
add(x,num);
sum(r)-sum(l-1);
每次x号位置修改num
求lr闭区间的和
**/
void add(int k,int num) {
while(k<=n) {
c[k]+=num;
k+=lowbit(k);
}
}
int sum(int k) {
int ans=0;
while(k) {
ans+=c[k];
k-=lowbit(k);
}
return ans;
}
void init(void) {
memset(ls,0,sizeof ls);
memset(lb,0,sizeof lb);
memset(rs,0,sizeof rs);
memset(rb,0,sizeof rb);
}
int main()
{
while(scanf("%d",&n)!=EOF) {
for(int i=1;i<=n;i++) {
scanf("%d",&a[i].v);
a[i].num=i;
}
sort(a+1,a+n+1,cmp);
for(int i=1;i<=n;i++) {
v[a[i].num]=i;
if(a[i].v==a[i+1].v) {
for(int j=i+1;j<=n;j++) {
v[a[j].num]=i;
if(a[j+1].v!=a[j].v) {
i=j;break;
}
}
}
}
/* for(int i=1;i<=n;i++)
cout << v[i] << " ";
cout << endl;*/
memset(c,0,sizeof c);
for(int i=1;i<=n;i++) {
ls[i]=sum(v[i]-1);
lb[i]=i-1-sum(v[i]);
add(v[i],1);
}
memset(c,0,sizeof c);
for(int i=n;i>=1;i--) {
rs[i]=sum(v[i]-1);
rb[i]=sum(n)-sum(v[i]);
add(v[i],1);
}
long long ans=0;
long long ans1=0;
long long ans2=0;
for(int i=1;i<=n;i++) {
ans1+=ls[i];
ans2+=lb[i];
}
ans=ans1*ans2;
for(int i=1;i<=n;i++) {
ans-=rs[i]*rb[i]; //a=c
ans-=lb[i]*rb[i]; //a=d
ans-=ls[i]*rs[i]; //b=c
ans-=ls[i]*lb[i]; //b=d
}
printf("%lld\n",ans);
}
return 0;
}
a≠b≠c≠d,1≤a<b≤n,1≤c<d≤n,Aa<Ab,Aa≠b≠c≠d,1≤a<b≤n,1≤c<d≤n,Aa<Ab,Ac>Ad.
rs[i]*rb[i]; //a=c
a≠b≠c≠d,1≤a<b≤n,1≤c<d≤n,Aa<Ab,Ac>Ad.
其中a,b,c,d两两互不相等,1<=a<b<=n ,1<=c<d<=n A[a]<A[b] A[c]>A[d] 其中a,b,c,d的组数
思路:先算一个总的数量=逆序对乘顺序对。然后再减去重复,发现只有a=c a=d b=c b=d
然后用树状数组维护,首先要离散化。
ls[i],lb[i],rs[i],rb[i]分别表示左边比当前位置小的,左边比当前位置大的,右边比当前位置小的,右边比当前位置大的。
逆序对数=sigma(lb[i])
顺序对数=sigma(ls[i])
.其他的四项画了草图可得,分别为:
rs[i]*rb[i] //a=c
lb[i]*rb[i] //a=d
ls[i]*rs[i] //b=c
ls[i]*lb[i] //b=d
#include<bits/stdc++.h>
#define maxn 55555
using namespace std;
int n;
int c[maxn];
int b[maxn];
int ls[maxn],lb[maxn],rs[maxn],rb[maxn];
///左边比自己小的,左边比自己大的,右边比自己小的,右边比自己大的
struct NODE{
int v,num;
}a[maxn];
int v[maxn];
bool cmp(const NODE X,const NODE Y) {
return X.v<Y.v;
}
int lowbit(int x) {
return x&-x;
}
/**单点修改区间求和**/
/**
add(x,num);
sum(r)-sum(l-1);
每次x号位置修改num
求lr闭区间的和
**/
void add(int k,int num) {
while(k<=n) {
c[k]+=num;
k+=lowbit(k);
}
}
int sum(int k) {
int ans=0;
while(k) {
ans+=c[k];
k-=lowbit(k);
}
return ans;
}
void init(void) {
memset(ls,0,sizeof ls);
memset(lb,0,sizeof lb);
memset(rs,0,sizeof rs);
memset(rb,0,sizeof rb);
}
int main()
{
while(scanf("%d",&n)!=EOF) {
for(int i=1;i<=n;i++) {
scanf("%d",&a[i].v);
a[i].num=i;
}
sort(a+1,a+n+1,cmp);
for(int i=1;i<=n;i++) {
v[a[i].num]=i;
if(a[i].v==a[i+1].v) {
for(int j=i+1;j<=n;j++) {
v[a[j].num]=i;
if(a[j+1].v!=a[j].v) {
i=j;break;
}
}
}
}
/* for(int i=1;i<=n;i++)
cout << v[i] << " ";
cout << endl;*/
memset(c,0,sizeof c);
for(int i=1;i<=n;i++) {
ls[i]=sum(v[i]-1);
lb[i]=i-1-sum(v[i]);
add(v[i],1);
}
memset(c,0,sizeof c);
for(int i=n;i>=1;i--) {
rs[i]=sum(v[i]-1);
rb[i]=sum(n)-sum(v[i]);
add(v[i],1);
}
long long ans=0;
long long ans1=0;
long long ans2=0;
for(int i=1;i<=n;i++) {
ans1+=ls[i];
ans2+=lb[i];
}
ans=ans1*ans2;
for(int i=1;i<=n;i++) {
ans-=rs[i]*rb[i]; //a=c
ans-=lb[i]*rb[i]; //a=d
ans-=ls[i]*rs[i]; //b=c
ans-=ls[i]*lb[i]; //b=d
}
printf("%lld\n",ans);
}
return 0;
}
a≠b≠c≠d,1≤a<b≤n,1≤c<d≤n,Aa<Ab,Aa≠b≠c≠d,1≤a<b≤n,1≤c<d≤n,Aa<Ab,Ac>Ad.
rs[i]*rb[i]; //a=c
a≠b≠c≠d,1≤a<b≤n,1≤c<d≤n,Aa<Ab,Ac>Ad.
相关文章推荐
- javascript-js 的prototype原型理解讲解
- squid简介
- node.js
- 对于RSA算法的一些理解
- Centos 常用命令笔记
- mysql数据库权限及编码
- 顺序表应用3:元素位置互换之移位算法
- mmap函数实现共享内存
- Java Web之Html
- refresh的停车场
- HDU 4808 Drunk(数学)
- 跟我一起写Makefile(6)--- Makefile里有什么+Makefile的文件名+引用其他的Makefile
- 概率主题模型与LDA模型公式推导(1)
- 36. Valid Sudoku | LeetCode
- Loadrunner并发用户与集合点讨论(转)
- HDU-3605 Escape
- 树莓派小白教程(二)
- 顺序表应用1:多余元素删除之移位算法
- Hibernate级联属性cascade
- UI标签在火狐浏览器中某些问题解决