hdu3015,poj1990树状数组

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3015

题意:给定n组数,每组数有值x和值h,求n组数两两的val的总和。将所有x和所有h分别离散化(不去重)变成x'和h',val(i,j)为abs(x'i-x'j)*min(hi',hj')。

如:

  x,    h——>x',h'

10,100——>1,1

50,500——>4,4

20,200——>3,3

20,100——>1,1

思路:只要把n*n优化成n*logn就可以过。

tip1:按照h'的值sort,并动态加点,每次加的点如果是已加点中h'最小的,那么min()中要取的值就为h'

tip2:离散化但是不去重,不需要unique

tip3:关于abs()部分的处理,两棵树状数组,一棵统计数量,一棵统计sum。abs()值为(大于x'的sum-大于x'的数量*x')+(小于x'的数量*x'-小于x'的sum)

tip4:res和sum树状数组均需要开long long

附上代码:

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int maxn=1e5+10;
int C1[maxn],C2[maxn],n;
int lowbit(int x)
{
    return x&-x;
}
void add1(int x,int c)
{
    for(;x<=n;x+=lowbit(x))
        C1[x]+=c;
}
void add2(int x,int c)
{
    for(;x<=n;x+=lowbit(x))
        C2[x]+=c;
}
int query1(int x)
{
    int res=0;
    for(;x;x-=lowbit(x))
        res+=C1[x];
    return res;
};
long long query2(int x)
{
    long long res=0;
    for(;x;x-=lowbit(x))
        res+=C2[x];
    return res;
}
struct node
{
    int x,h;
}p[maxn];
bool cmp(node a,node b)
{
    if(a.h==b.h)return a.x>b.x;
    else return a.h>b.h;
}

int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        memset(C1,0,sizeof C1);
        memset(C2,0,sizeof C2);
        int x[maxn]={0},h[maxn]={0};
        for(int i=0;i<n;i++)scanf("%d%d",&p[i].x,&p[i].h),x[i]=p[i].x,h[i]=p[i].h;
        sort(x,x+n);
        sort(h,h+n);
        sort(p,p+n,cmp);
        long long res=0;
        for(int i=0;i<n;i++)
        {
            int tmpx=lower_bound(x,x+n,p[i].x)-x+1;
            int tmph=lower_bound(h,h+n,p[i].h)-h+1;
            //cout<<tmpx<<" "<<tmph<<endl;
            res+=1ll*tmph*(-1ll*tmpx*(query1(n)-query1(tmpx))+1ll*tmpx*query1(tmpx-1)+query2(n)-query2(tmpx)-query2(tmpx-1));
            add1(tmpx,1);
            add2(tmpx,tmpx);
        }
        printf("%lld
",res);
    }
    return 0;
}

poj1990,一道类似的题

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int maxn=2e4+10;
int n,C1[maxn],C2[maxn],maxp;
struct node
{
    int v,place;
}p[maxn];
bool cmp(node a,node b)
{
    if(a.v==b.v)return a.place>b.place;
    else return a.v>b.v;
}
int lowbit(int x)
{
    return x&-x;
}
void add1(int x,int c)
{
    for(;x<=maxp;x+=lowbit(x))
        C1[x]+=c;
}
void add2(int x,int c)
{
    for(;x<=maxp;x+=lowbit(x))
        C2[x]+=c;
}
int query1(int x)
{
    int res=0;
    for(;x;x-=lowbit(x))
        res+=C1[x];
    return res;
}
long long query2(int x)
{
    long long res=0;
    for(;x;x-=lowbit(x))
        res+=C2[x];
    return res;
}
int main()
{
    scanf("%d",&n);
    for(int i=0;i<n;i++)scanf("%d%d",&p[i].v,&p[i].place),maxp=max(maxp,p[i].place);
    sort(p,p+n,cmp);
    long long res=0;
    for(int i=n-1;i>=0;i--)
    {
        //cout<<p[i].v<<" "<<p[i].place<<endl;
        res+=1ll*p[i].v*(query2(maxp)-query2(p[i].place)-p[i].place*(query1(maxp)-query1(p[i].place))+p[i].place*query1(p[i].place-1)-query2(p[i].place-1));
        add1(p[i].place,1);
        add2(p[i].place,p[i].place);
        //cout<<res<<endl;
    }
    printf("%lld
",res);
    return 0;
}
原文地址:https://www.cnblogs.com/myrtle/p/11756459.html