POJ 2299 Ultra-QuickSort
题目链接:Ultra-QuickSort
Solution
由于数组元素各不相同且最大的可能到999,999,999 ,先将n个元素的数组元素转换为1-n的某个排列,
该排列与原数组各元素对应位置各元素相对大小关系一致,然后对其求逆序对个数即得答案,我用的树状数组版。
Code
树状数组版:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 500001
int a[N+2],c[N+2],n,order[N+1];
struct node
{
int key;
int id;
bool const operator<(const struct node& a)const
{
return key<a.key;
}
} data[N+2];
inline int lowbit(int i){
return i&(-i);
}
inline int sum(int i)
{
int ans=0;
for(;i>0;i-=lowbit(i))
ans+=c[i];
return ans;
}
inline void add(int i,int v)
{
for(;i<=n;i+=lowbit(i))
c[i]+=v;
}
int main()
{
while(~scanf("%d",&n)&&n){
memset(c,0,sizeof(c));
long long ans=0;
for(int i=1; i<=n; i++)
{
cin>>data[i].key;
data[i].id=i;
}
sort(data+1,data+n+1);
for(int i=1;i<=n;++i)
order[data[i].id]=i;
for(int i=1; i<=n;i++)
{
add(order[i],1);
ans+=i-1-sum(order[i]-1);
}
cout<<ans<<endl;
}
return 0;
}
嗯 刚学树状数组,再接着补。
HDU 3874 Necklace
题目链接:
Necklace
Time Limit: 15000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Description
大意是说有一串珠子,每个珠子都有自己的欣赏值value,(0<=value<=1e6)现在给你一串珠子每个的欣赏值,
并给出一些询问,查询某个区间总欣赏值是多少,但是一个约定就是如果这个区间内部有两个珠子的欣赏值是
一样的,那么他们就视为一个,即相同值只计算一次。
Code
#include <cstdio>
#include <cstring>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
#define ll long long
const int N=5e4;
const int M=2e5;
const int mmax=1e6;
int a[N+2],n,m;
int first[mmax+2];//存放value值第一次出现的位置
ll c[N+2],ans[M+2];//ans存放每次询问的答案
struct node
{
int l,r;
int id;
bool const operator<(const struct node& a)const
{
return r<a.r; //将询问按右端点由小到大排列
}
}query[M+2];
inline int lowbit(int i){
return i&(-i);
}
inline ll sum(int i)
{
ll ans=0;
for(;i>0;i-=lowbit(i))
ans+=c[i];
return ans;
}
inline void add(int i,int v)
{
for(;i<=n;i+=lowbit(i))
c[i]+=v;
}
int main()
{
int t;
scanf("%d",&t);
getchar();
while(t--){
scanf("%d",&n);
memset(c,0,sizeof(c));
memset(first,0,sizeof(first));
for(int i=1; i<=n; i++)
{
scanf("%d",&a[i]);
if(!first[a[i]])
first[a[i]]=i;
add(i,a[i]);
}
scanf("%d",&m);
for(int i=1;i<=m;++i){
scanf("%d%d",&query[i].l,&query[i].r);
query[i].id=i;
}
sort(query+1,query+m+1);
int r=1;
for(int i=1; i<=m;i++)
{
for(int j=r;j<=query[i].r;++j){
if(first[a[j]]!=j){
add(first[a[j]],-a[j]);//加负值, 将之前出现过的value值减去
first[a[j]]=j;
}
}
r=query[i].r;
ans[query[i].id]=sum(query[i].r)-sum(query[i].l-1);
}
for(int i=1;i<=m;++i)
printf("%I64d\n",ans[i]);
}
return 0;
}