POJ 3928 Ping pong 树状数组模板题

开始用瓜神说的方法撸了一发线段树,早上没事闲的看了一下树状数组的方法,于是又写了一发树状数组

树状数组:

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <climits>
#include <string>
#include <iostream>
#include <map>
#include <cstdlib>
#include <list>
#include <set>
#include <queue>
#include <stack>
using namespace std;
#define INF 0xfffffff
const int maxn=100010;
typedef long long LL;
int c[maxn],lmin[maxn],lmax[maxn],rmin[maxn],rmax[maxn],a[maxn];
int lowbit(int x)
{
    return x&(-x);
}
void update(int i,int l)
{
    while(i<maxn)
    {
        c[i]+=l;
        i+=lowbit(i);
    }
}
int sum(int i)
{
    int ans=0;
    while(i>0)
    {
        ans+=c[i];
        i-=lowbit(i);
    }
    return ans;
}
int main()
{
    int t,n;
    cin>>t;
    while(t--)
    {
        cin>>n;
        for(int i=1;i<=n;i++)
        cin>>a[i];
        memset(c,0,sizeof(c));
        for(int i=1;i<=n;i++)
        {
            update(a[i],1);
            lmin[i]=sum(a[i]-1);
            lmax[i]=i-1-lmin[i];
            //cout<<lmin[i]<<" "<<lmax[i]<<endl;
        }
        memset(c,0,sizeof(c));
        for(int i=n;i>=1;i--)
        {
            update(a[i],1);
            rmin[i]=sum(a[i]-1);
            rmax[i]=n-i-rmin[i];
            //cout<<rmin[i]<<" "<<rmax[i]<<endl;
        }
        LL ans=0;
        for(int i=1;i<=n;i++)
        {
            ans+=lmin[i]*rmax[i];
            ans+=lmax[i]*rmin[i];
        }
        cout<<ans<<endl;
    }
    return 0;
}

线段树:

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <climits>
#include <string>
#include <iostream>
#include <map>
#include <cstdlib>
#include <list>
#include <set>
#include <queue>
#include <stack>
using namespace std;
#define INF 0xfffffff
typedef long long LL;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define maxn 100000+10
int a[maxn];
int sum[maxn<<2],zmax[maxn],zmin[maxn],ymax[maxn],ymin[maxn];
void pushup(int rt)
{
    sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
void build(int l,int r,int rt)
{
    sum[rt]=0;
    if(l==r) return ;
    int m=(l+r)>>1;
    build(lson);
    build(rson);
}
int ask(int L,int R,int l,int r,int rt)
{
    if(L<=l&&R>=r) return sum[rt];
    int m=(l+r)>>1;
    int ans=0;
    if(L<=m) ans+=ask(L,R,lson);
    if(R>m) ans+=ask(L,R,rson);
    return ans;
}
void update(int pos,int add,int l,int r,int rt)
{
    if(l==r)
    {
        sum[rt]=1;
        return ;
    }
    int m=(l+r)>>1;
    if(pos<=m) update(pos,add,lson);
    else update(pos,add,rson);
    pushup(rt);
}
int main()
{
    int t;
    cin>>t;
    int n;
    while(t--)
    {
        cin>>n;
        int Max=0;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            Max=max(Max,a[i]);
        }
        build(1,Max,1);
        for(int i=1;i<=n;i++)
        {
            zmin[i]=ask(1,a[i],1,Max,1);
            zmax[i]=ask(1,Max,1,Max,1)-zmin[i];
            update(a[i],1,1,Max,1);
        }
        build(1,Max,1);
        for(int i=n;i>=1;i--)
        {
            ymin[i]=ask(1,a[i],1,Max,1);
            ymax[i]=ask(1,Max,1,Max,1)-ymin[i];
            update(a[i],1,1,Max,1);
        }
        LL ans=0;
        for (int i = 1; i <= n; i++)
        {
			ans += zmin[i] * ymax[i];
			ans += zmax[i] * ymin[i];
		}
		cout<<ans<<endl;
    }
    return 0;
}
时间: 2024-12-06 01:13:06

POJ 3928 Ping pong 树状数组模板题的相关文章

HDU 2492 Ping pong (树状数组)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2492 Ping pong Problem Description N(3<=N<=20000) ping pong players live along a west-east street(consider the street as a line segment). Each player has a unique skill rank. To improve their skill rank

poj3928 Ping pong 树状数组

http://poj.org/problem?id=3928 Ping pong Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 2087   Accepted: 798 Description N(3<=N<=20000) ping pong players live along a west-east street(consider the street as a line segment). Each player

uva 1428 - Ping pong(树状数组)

题目链接:uva 1428 - Ping pong 题目大意:一条大街上住着n个乒乓球爱好者,经常组织比赛.每个人都有一个不同的能力值,每场比赛需要3个人,裁判要住在两个选手之间,并且能力值也要在选手之间,问说最多能举行多少场比赛. 解题思路:预处理出bi和ci分别表示说在1~i中能力值比第i个人小的人和i+1~n中能力值比第i个人小的.处理过程用树状数组维护即可. #include <cstdio> #include <cstring> #include <algorith

UVALive 4329 Ping pong (树状数组)

白书上的例题.花了很多时间在找bug上,刚学树状数组,这道题add操作时要注意上限不是n. #include <bits/stdc++.h> using namespace std; #define ll long long const ll maxn = 1e5 + 10; ll C[maxn]; ll n; inline ll lowbit(ll x) { return x & (-x); } ll sum(ll x) { ll ret = 0; while(x > 0) {

LA4329 Ping pong 树状数组

题意:一条大街上住着n个乒乓球爱好者,经常组织比赛切磋技术.每个人都有一个能力值a[i].每场比赛需要三个人:两名选手,一名裁判.他们有个奇怪的约定,裁判必须住在两名选手之间,而裁判的能力值也必须在两名选手之间.问一共能组织多少种比赛. 分析:考虑第i个人,假设a1到ai-1中有ci个比ai小,那么就有(i-1)-ci个比ai大:同理,如果ai+1到an中有di个比ai小,那么就有(n-i)-di个比ai大.i当裁判就有:ci * (n-i-di) + (i-1-ci)*di种比赛. 然后问题就

树状数组模板题(特强浓雾

#include<bits/stdc++.h> using namespace std; int a,b; int c[100005]; void add(int x,int y)//树状数组初始化 { while(x<=a+b) c[x]+=y,x+=x&-x;//露馅了噗哈哈哈哈哈哈蛤哈哈哈哈哈哈 } int ask(int x)//询问 { int ans=0; while(x) ans+=c[x],x-=x&-x; return ans; } int main()

POJ-3928 Ping pong(树状数组)

Ping pong Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 2985   Accepted: 1104 Description N(3<=N<=20000) ping pong players live along a west-east street(consider the street as a line segment). Each player has a unique skill rank. To i

UVA1428 - Ping pong(树状数组)

题目链接 题目大意:有N个人,每个人都有一个技能值ai,现在要开展乒乓球比赛,要求要有两个选手和一个裁判,要求裁判需要在两名选手的中间而且技能值也是在两名选手的中间,问可以开展多少场比赛. 解题思路:对于第i个选手当裁判的话,设它前面位置的选手有ci个技能值比它低的,那么就有i - 1 - ci个比它高的,对于第i选手后面的位置,同样有di个技能值比它低的,那么就有N - i - di个比它高的.组合一下:ci?(N - i - di) + (i - 1 - ci) ? di.那么对于ci的值,

树状数组模板题 P1904

Description 给定一个长度为n的整数数组A[1].A[2].-.A[n](-10^9 Input 第一行包含两个整数n和m,表示数组有n个元素,m表示有m个操作:接下来的一行包含n个整数,第i个整数表示A[i]:再接下来的m行,每行表示一个操作. Output 按输入顺序输出操作2的结果. Hint 反正要用long long Solution 嗯,这个题,告诉我们,位运算要打括号... #include<cstdio> #include<cstring> #includ