CDOJ 1276 浑身难受 每周一题 div1 树状数组

浑身难受

题目连接:

http://acm.uestc.edu.cn/#/problem/show/1276

Description

772002生病了!他觉得浑身难受,作为暴力界的致命人物,772002对于生病有着自己独特的认知与治疗方法.

772002治疗生病的方法就是去找一名叫人可木主的医生!当然请人可木主治疗的代价可不低!人可木主作为智商街上智商最高的人,他给人治疗的花费计算非常奇怪!人可木主会给病人一个{1,2,3,4}的排列t,之后他会通过玄学将病人的病症状况转换为一个N的排列,之后人可木主会询问病人这个N的排列中有多少对四元组( p[A1],p[A2],p[A3],p[A4] ) (A1<A2<A3<A4 )的大小关系与人可木主所给的4的排列t的大小关系相同。

当然,只有回答正确,人可木主才会医治病人。

恰逢情人节前后,学姐卿和Final潘都已经被妹纸约走了,浑身难受的772002又无法发挥出自己的暴力实力,只能把这个艰难的任务交给你了。

Input

第一行一个整数N(1<=N<=2000)
第二行4 个整数A[1],A[2],A[3],A4
第三行n个整数,p[1],p[2],....,pn

Output

输出仅一行,输出有多少A排列满足题意

Sample Input

5
1 2 3 4
1 2 3 4 5

Sample Output

5

Hint

题意

题解:

做这道题你需要点出来的技能点是 树状数组

如果你会用树状数组求逆序数的个数的话,那么这道题也可以解决了,因为本质上就是求逆序数。

首先这道题怎么做呢?

总共有24种情况。

最智障的做法,就是把所有情况全部都讨论一下,都用两个树状数组去处理就好了,这个只要有耐心,慢慢写就好了。

但是智障还是会遇到2413这个顺序不会暴力,但是他灵机一动,发现2413 = 24xx-2431-2411-2433,然后容斥乱搞就好了,于是智障青年花了两个小时怼完了这道题。


一般青年说,这道题明显可以简化:

可以分三派:

1、1和4不连在一起,那么就n方枚举2和3的位置,剩下的1和4个数可以预处理算出来。

2、1和3不连在一起,类似1。

3、2和4不连在一起,把序列大小反过来,当成2做

然后2413用容斥做。


文艺青年说,这道题明显只用分成两种:2413和其他,2413用容斥做。

所以只用写一种就好了。

为什么呢?

让我们仔细想想,为什么一般青年的那3种情况可以做?

我们首先把平面切成3*3的小格子。

因为这些序列中存在(i,pi),(j,pj)两个点,使得每个格子内最多一个点

然后我们就暴力枚举这两个点,然后算部分和就好了。

于是就完了。

文艺代码 by ftiasch

#include<bits/stdc++.h>
using namespace std;

const int maxn = 2050;
int n;
int a[maxn];
int sum[maxn][maxn];
int signum(int x)
{
    if(x==0)return 0;
    if(x<0)return -1;
    return 1;
}
int getsum(int x0,int x1,int y0,int y1)
{
    x0++;
    y0++;
    return sum[x0][y0]-sum[x0][y1]-sum[x1][y0]+sum[x1][y1];
}
long long solve(int p[])
{
    pair<int,int>temp;
    if(abs(p[1]-p[3])!=1)
        temp=make_pair(0,2);
    else if(abs(p[0]-p[3])!=1)
        temp=make_pair(1,2);
    else if(abs(p[0]-p[2])!=1)
        temp=make_pair(1,3);
    else
        temp=make_pair(1,2);
    pair<int,int>p1;
    p1=make_pair(p[temp.first],p[temp.second]);
    int tmpSignum = signum(p1.first-p1.second);
    long long ans = 0;
    for(int i=0;i<n;i++)
    {
        for(int j=i+1;j<n;j++)
        {
            if(signum(a[i]-a[j])==tmpSignum)
            {
                int lower[4]={-1,-1,-1,-1};
                int upper[4]={n,n,n,n};
                lower[p1.first]=a[i],upper[p1.first]=a[i];
                lower[p1.second]=a[j],upper[p1.second]=a[j];
                for(int k=1;k<4;k++)
                    lower[k]=max(lower[k],lower[k-1]);
                for(int k=2;k>=0;k--)
                    upper[k]=min(upper[k],upper[k+1]);
                long long pro=1;
                if(temp.first!=0)
                {
                    int x = p[0];
                    pro*=getsum(-1,i,lower[x],upper[x]);
                }
                if(temp.first+1!=temp.second)
                {
                    int x = p[temp.first+1];
                    pro*=getsum(i,j,lower[x],upper[x]);
                }
                if(temp.second!=3)
                {
                    int x = p[3];
                    pro*=getsum(j,n,lower[x],upper[x]);
                }
                ans+=pro;
            }
        }
    }
    return ans;
}
int main()
{
    scanf("%d",&n);
    int p[4];
    for(int i=0;i<4;i++)
        scanf("%d",&p[i]),p[i]--;
    for(int i=0;i<n;i++)
        scanf("%d",&a[i]),a[i]--;
    for(int i=0;i<n;i++)
        sum[i][a[i]]++;
    for(int i=n-1;i>=0;i--)
        for(int j=n-1;j>=0;j--)
            sum[i][j]+=sum[i+1][j]+sum[i][j+1]-sum[i+1][j+1];
    long long ans = solve(p);
    if(p[0]==1&&p[1]==3&&p[2]==0&&p[3]==2)
    {
        int p1[4]={2,3,0,1};
        ans-=solve(p1);
    }
    else if(p[0]==2&&p[1]==0&&p[2]==3&&p[3]==1)
    {
        int p1[4]={1,0,3,2};
        ans-=solve(p1);
    }
    cout<<ans<<endl;
}

一般青年代码 by xiper

#include <bits/stdc++.h>
#define lowbit(x) ((x)&(-x))
using namespace std;
const int maxn = 2000 + 15;
int n , a[5] , p[maxn] , lft[maxn] , rht[maxn] , ta , tb ;
void update(int * bit ,int x , int y) { while(x <= n){ bit[x] += y , x += lowbit(x);} }
int  prefixsum(int * bit , int x) { int res = 0 ; while(x){ res += bit[x] , x-=lowbit(x);} return res;}
int  query(int * bit , int l , int r) { return prefixsum( bit , r ) - prefixsum( bit , l - 1 ); }

long long solve_normal(){
    long long res = 0;
    int sign = a[1] < a[3];
    for(int i = 1 ; i <= n ; ++ i){
        memset( lft , 0 , sizeof( lft ) );
        memset( rht , 0 , sizeof( rht ) );
        for(int j = n ; j > i ; -- j) update( rht , p[j] , 1 );
        for(int j = i + 1 ; j <= n ; ++ j){
            update( rht , p[j] , -1 ); // Remove Element from Right
            bool UpdateOperation = true;
            if( ( p[i] < p[j] ) != sign ) UpdateOperation = false;
            if(UpdateOperation){
                if(a[2] < a[4]){
                    if( ta == 1 && tb == 3 ) res += query( lft , min(p[i],p[j]) + 1 , max(p[i],p[j]) - 1 ) * query( rht , max(p[i],p[j]) + 1 , n );
                    else if( ta == 2 && tb == 3 ) res += prefixsum( lft , min(p[i],p[j]) - 1 ) * query( rht , max(p[i],p[j]) + 1 , n );
                    else if( ta == 2 && tb == 4 ) res += prefixsum( lft , min(p[i],p[j]) - 1 ) * query( rht , min(p[i],p[j]) + 1 , max(p[i],p[j]) - 1 );
                }else{
                    if( ta == 1 && tb == 3 ) res += query( lft , max(p[i],p[j]) + 1 , n ) * query( rht , min(p[i],p[j]) + 1 , max(p[i],p[j]) - 1 );
                    else if( ta == 2 && tb == 3 ) res += query( lft , max(p[i],p[j]) + 1 , n ) * prefixsum( rht , min(p[i],p[j]) - 1 );
                    else if( ta == 2 && tb == 4 ) res += query( lft , min(p[i],p[j]) + 1 , max(p[i],p[j]) - 1 ) * prefixsum( rht , min(p[i],p[j]) - 1 );
                }
            }
            update( lft , p[j] , 1 ); // Add Element to Left;
        }
    }
    return res;
}

long long solve_right(){
    long long res = 0;
    int sign = a[2] < a[4];
    update( lft , p[1] , 1 );
    for(int i = 2 ; i <= n ; ++ i){
        memset( rht , 0 , sizeof( rht ) );
        for(int j = i + 1 ; j <= n ; ++ j){
            bool UpdateOperation = true;
            if( ( p[i] < p[j] ) != sign ) UpdateOperation = false;
            if(UpdateOperation){
                if(a[1] < a[3]) res += prefixsum( lft , min(p[i],p[j]) - 1 ) * query( rht , max(p[i],p[j]) + 1 , n );
                else res += query( lft , max(p[i],p[j]) + 1 , n ) * prefixsum( rht , min(p[i],p[j]) - 1 );
            }
            update( rht , p[j] , 1 );
        }
        update( lft , p[i] , 1 );
    }
    return res;
}

long long solve_special_2413(){
    long long res = 0 ;
    for(int i = 1 ; i <= n ; ++ i){
        memset( rht , 0 , sizeof( rht ) );
        memset( lft , 0 , sizeof( lft ) );
        long long cur = 0 ;
        for(int j = i + 1 ; j <= n ; ++ j) if(p[j] > p[i]) update( rht , p[j] , 1 );
        for(int j = i + 1 ; j <= n ; ++ j){
            bool UpdateOperation = true;
            if( p[j] > p[i] ) UpdateOperation = false;
            if( UpdateOperation ) res += cur;
            else{
                cur -= query( lft , p[j] + 1 , n );
                update( rht , p[j] , -1 );
                cur += prefixsum( rht , p[j] - 1 );
                update( lft , p[j] , 1 );
            }
        }
    }
    return res;
}

long long solve_special_3142(){
    long long res = 0 ;
    for(int i = 1 ; i <= n ; ++ i){
        memset( rht , 0 , sizeof( rht ) );
        memset( lft , 0 , sizeof( lft ) );
        long long cur = 0;
        for(int j = i + 1 ; j <= n ; ++ j) if(p[j] < p[i]) update( rht , p[j] , 1 );
        for(int j = i + 1 ; j <= n ; ++ j){
            bool UpdateOperation = true;
            if( p[j] < p[i] ) UpdateOperation = false;
            if( UpdateOperation ) res += cur;
            else{
                cur -= prefixsum( lft , p[j] - 1 );
                update( rht , p[j] , -1 );
                cur += query( rht , p[j] + 1 , n );
                update( lft , p[j] , 1 );
            }
        }
    }
    return res;
}

long long solve_mid(){
    int sign = a[2] < a[3];
    long long res = 0;
    update( lft , p[1] , 1 );
    for(int i = 2 ; i <= n ; ++ i){
        memset( rht , 0 , sizeof( rht ) );
        for(int j = i + 1 ; j <= n ; ++ j) update( rht , p[j] , 1 );
        for(int j = i + 1 ; j <= n ; ++ j){
            update( rht , p[j] , -1 );
            bool UpdateOperation = true;
            if( ( p[i] < p[j] ) != sign ) UpdateOperation = false;
            if(UpdateOperation){
                int l , r ;
                if(a[1] < min( a[2] , a[3] )) l = prefixsum( lft , min( p[i] , p[j] ) - 1 );
                else if(a[1] > max( a[2] , a[3] ) ) l = query( lft , max( p[i] , p[j] ) + 1 , n );
                else l = query( lft , min( p[i] , p[j] ) + 1 , max( p[i] , p[j] ) - 1 );
                if(a[4] < min( a[2] , a[3] )) r = prefixsum( rht , min( p[i] , p[j] ) - 1 );
                else if(a[4] > max( a[2] , a[3] ) ) r = query( rht , max( p[i] , p[j] ) + 1 , n );
                else r = query( rht , min( p[i] , p[j] ) + 1 , max( p[i] , p[j] ) - 1 );
                res += 1LL * l * r ;
            }
        }
        update( lft , p[i] , 1 );
    }
    return res;
}

int main(int argc,char *argv[]){
    scanf("%d" ,&n);
    for(int i = 1 ; i <= 4 ; ++ i) scanf("%d" , a + i);
    for(int i = 1 ; i <= n ; ++ i) scanf("%d" , p + i);
    int ID = a[1] * 1000 + a[2] * 100 + a[3] * 10 + a[4];
    ta = min( a[1] , a[3] ) , tb = max( a[1] , a[3] );
    long long ans = 0;
    if( (ta == 1 && tb == 3) || (ta == 2 && tb == 3) || (ta == 2 && tb == 4) )  ans = solve_normal();
    else if( ta == 1 && tb == 4 ) ans = solve_right();
    else if(ID == 2413) ans = solve_special_2413();
    else if(ID == 3142) ans = solve_special_3142();
    else ans = solve_mid();
    cout << ans << endl;
    return 0;
}

智障青年代码 by qscqesze

#include<bits/stdc++.h>
using namespace std;
const int maxn = 2050;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
struct bit
{
    int a[maxn];
    void init()
    {
        memset(a,0,sizeof(a));
    }
    int lowbit(int x)
    {
        return x&(-x);
    }
    int query(int x)
    {
        int ans = 0;
        for(int i=x;i;i-=lowbit(i))
            ans+=a[i];
        return ans;
    }
    void update(int x,int val)
    {
        for(int i=x;i<maxn;i+=lowbit(i))
            a[i]+=val;
    }
}L,R;
int n,a[maxn],p[maxn];
long long solve1234()
{
    L.init(),R.init();
    long long ans = 0;
    for(int i=1;i<=n;i++)
    {
        L.update(a[i],1);
        R.init();
        for(int j=n;j>i;j--)
        {
            R.update(a[j],1);
            if(a[i]<a[j])
                ans+=L.query(a[i]-1)*(R.query(2010)-R.query(a[j]));
        }
    }
    return ans;
}
long long solve1243()
{
    L.init(),R.init();
    long long ans = 0;
    for(int i=1;i<=n;i++)
    {
        L.update(a[i],1);
        R.init();
        for(int j=i+1;j<=n;j++)
        {
            R.update(a[j],1);
            if(a[i]<a[j])
                ans+=L.query(a[i]-1)*(R.query(2010)-R.query(a[j]));
        }
    }
    return ans;
}
long long solve1324()
{
    L.init(),R.init();
    long long ans = 0;
    for(int i=1;i<=n;i++)
    {
        L.update(a[i],1);
        R.init();
        for(int j=n;j>i;j--)
        {
            R.update(a[j],1);
            if(a[i]>a[j])
                ans+=L.query(a[j]-1)*(R.query(2010)-R.query(a[i]));
        }
    }
    return ans;
}
long long solve1342()
{
    L.init(),R.init();
    long long ans = 0;
    for(int i=1;i<=n;i++)
    {
        L.update(a[i],1);
        R.init();
        for(int j=i+1;j<=n;j++)
        {
            R.update(a[j],1);
            if(a[i]>a[j])
                ans+=L.query(a[j]-1)*(R.query(2010)-R.query(a[i]));
        }
    }
    return ans;
}
long long solve1423()
{
    L.init(),R.init();
    long long ans = 0;
    for(int i=1;i<=n;i++)
    {
        L.update(a[i],1);
        R.init();
        for(int j=n;j>i;j--)
        {
            R.update(a[j],1);
            if(a[i]>a[j])
                ans+=L.query(a[j]-1)*(R.query(a[i]-1)-R.query(a[j]));
        }
    }
    return ans;
}
long long solve1432()
{
    L.init(),R.init();
    long long ans = 0;
    for(int i=1;i<=n;i++)
    {
        L.update(a[i],1);
        R.init();
        for(int j=i+1;j<=n;j++)
        {
            R.update(a[j],1);
            if(a[i]>a[j])
                ans+=L.query(a[j]-1)*(R.query(a[i])-R.query(a[j]));
        }
    }
    return ans;
}
long long solve2134()
{
    L.init(),R.init();
    long long ans = 0;
    for(int i=n;i>=1;i--)
    {
        L.update(a[i],1);
        R.init();
        for(int j=i-1;j>=1;j--)
        {
            R.update(a[j],1);
            if(a[i]>a[j])
                ans+=(L.query(2010)-L.query(a[i]))*R.query(a[j]-1);
        }
    }
    return ans;
}
long long solve2143()
{
    L.init(),R.init();
    long long ans = 0;
    for(int i=1;i<=n;i++)
    {
        L.update(a[i],1);
        R.init();
        for(int j=i+1;j<=n;j++)
        {
            R.update(a[j],1);
            if(a[j]>a[i])
                ans+=(L.query(a[j]-1)-L.query(a[i]))*(R.query(2010)-R.query(a[j]));
        }
    }
    return ans;
}
long long solve3241();
long long solve2314()
{
    for(int i=1;i<=n;i++)
        a[i]=n-a[i]+1;
    return solve3241();
}
long long solve2341()
{
    L.init(),R.init();
    long long ans = 0;
    for(int i=n;i>=1;i--)
    {
        L.update(a[i],1);
        R.init();
        for(int j=i-1;j>=1;j--)
        {
            R.update(a[j],1);
            if(a[i]>a[j])
                ans+=L.query(a[j]-1)*(R.query(a[i]-1)-R.query(a[j]));
        }
    }
    return ans;
}
long long solve2431();
long long solve2413()//24xx-2431-2411-2433
{
    L.init(),R.init();
    long long ans = -solve2431();
    for(int i=1;i<=n;i++)
    {
        R.init();
        for(int j=n;j>i;j--)
        {
            R.update(a[j],1);
            if(a[j]>a[i])
            {
                ans+=(R.query(a[j]-1)*(R.query(a[j]-1)-1))/2;
                ans-=(R.query(a[i]-1)*(R.query(a[i]-1)-1))/2;
                ans-=((R.query(a[j]-1)-R.query(a[i]))*((R.query(a[j]-1)-R.query(a[i]))-1))/2;
            }
        }
    }
    return ans;
}
long long solve2431()
{
    L.init(),R.init();
    long long ans = 0;
    for(int i=n;i>=1;i--)
    {
        L.update(a[i],1);
        R.init();
        for(int j=i-1;j>=1;j--)
        {
            R.update(a[j],1);
            if(a[j]<a[i])
                ans+=L.query(a[j]-1)*(R.query(2010)-R.query(a[i]));
        }
    }
    return ans;
}
long long solve3124()
{
    L.init(),R.init();
    long long ans = 0;
    for(int i=n;i>=1;i--)
    {
        L.update(a[i],1);
        R.init();
        for(int j=i-1;j>=1;j--)
        {
            R.update(a[j],1);
            if(a[i]<a[j])
                ans+=(L.query(2010)-L.query(a[j]))*(R.query(a[i]-1));
        }
    }
    return ans;
}
long long solve3142()
{
    for(int i=1;i<=n;i++)
        a[i]=n-a[i]+1;
    return solve2413();
}
long long solve3214()
{
    L.init(),R.init();
    long long ans = 0;
    for(int i=n;i>=1;i--)
    {
        L.update(a[i],1);
        R.init();
        for(int j=i-1;j>=1;j--)
        {
            R.update(a[j],1);
            if(a[j]>a[i])
                ans+=(L.query(2010)-L.query(a[j]))*(R.query(a[j]-1)-R.query(a[i]));
        }
    }
    return ans;
}
long long solve3241()
{
    L.init(),R.init();
    long long ans = 0;
    for(int i=1;i<=n;i++)
    {
        L.update(a[i],1);
        R.init();
        for(int j=n;j>i;j--)
        {
            R.update(a[j],1);
            if(a[j]>a[i])
                ans+=(L.query(a[j]-1)-L.query(a[i]))*(R.query(a[i]-1));
        }
    }
    return ans;
}
long long solve3412()
{
    L.init(),R.init();
    long long ans = 0;
    for(int i=n;i>=1;i--)
    {
        L.update(a[i],1);
        R.init();
        for(int j=i-1;j>=1;j--)
        {
            R.update(a[j],1);
            if(a[i]<a[j])
                ans+=(L.query(a[j]-1)-L.query(a[i]))*(R.query(2010)-R.query(a[j]));
        }
    }
    return ans;
}
long long solve3421()
{
    L.init(),R.init();
    long long ans = 0;
    for(int i=1;i<=n;i++)
    {
        L.update(a[i],1);
        R.init();
        for(int j=n;j>i;j--)
        {
            R.update(a[j],1);
            if(a[i]>a[j])
                ans+=(L.query(a[i]-1)-L.query(a[j]))*(R.query(a[j]-1));
        }
    }
    return ans;
}
long long solve4123()
{
    L.init(),R.init();
    long long ans = 0;
    for(int i=1;i<=n;i++)
    {
        L.update(a[i],1);
        R.init();
        for(int j=i+1;j<=n;j++)
        {
            R.update(a[j],1);
            if(a[j]>a[i])
                ans+=(L.query(2010)-L.query(a[j]))*(R.query(a[j]-1)-R.query(a[i]));
        }
    }
    return ans;
}
long long solve4132()
{
    for(int i=1;i<=n;i++)
        a[i]=n-a[i]+1;
    return solve1423();
}
long long solve4213()
{
    L.init(),R.init();
    long long ans = 0;
    for(int i=1;i<=n;i++)
    {
        L.update(a[i],1);
        R.init();
        for(int j=i+1;j<=n;j++)
        {
            R.update(a[j],1);
            if(a[j]>a[i])
                ans+=(L.query(2010)-L.query(a[j]))*(R.query(a[i]-1));
        }
    }
    return ans;
}
long long solve4231()
{
    L.init(),R.init();
    long long ans = 0;
    for(int i=1;i<=n;i++)
    {
        L.update(a[i],1);
        R.init();
        for(int j=n;j>i;j--)
        {
            R.update(a[j],1);
            if(a[j]>a[i])
                ans+=(L.query(2010)-L.query(a[j]))*(R.query(a[i]-1));
        }
    }
    return ans;
}
long long solve4312()
{
    L.init(),R.init();
    long long ans = 0;
    for(int i=1;i<=n;i++)
    {
        L.update(a[i],1);
        R.init();
        for(int j=i+1;j<=n;j++)
        {
            R.update(a[j],1);
            if(a[i]>a[j])
                ans+=(L.query(2010)-L.query(a[i]))*R.query(a[j]-1);
        }
    }
    return ans;
}
long long solve4321()
{
    L.init(),R.init();
    long long ans = 0;
    for(int i=1;i<=n;i++)
    {
        L.update(a[i],1);
        R.init();
        for(int j=i+1;j<=n;j++)
        {
            R.update(a[j],1);
            if(a[j]<a[i])
                ans+=(L.query(2010)-L.query(a[i]))*(R.query(a[i]-1)-R.query(a[j]));
        }
    }
    return ans;
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=4;i++)
        p[i]=read();
    for(int i=1;i<=n;i++)
        a[i]=read();
    int id=p[1]*1000+p[2]*100+p[3]*10+p[4];
    long long ans = 0;
    if(id==1234)ans=solve1234();
    if(id==1243)ans=solve1243();
    if(id==1324)ans=solve1324();
    if(id==1342)ans=solve1342();
    if(id==1423)ans=solve1423();
    if(id==1432)ans=solve1432();
    if(id==2134)ans=solve2134();
    if(id==2143)ans=solve2143();
    if(id==2341)ans=solve2341();
    if(id==2314)ans=solve2314();
    if(id==2413)ans=solve2413();
    if(id==2431)ans=solve2431();
    if(id==3124)ans=solve3124();
    if(id==3142)ans=solve3142();
    if(id==3214)ans=solve3214();
    if(id==3241)ans=solve3241();
    if(id==3412)ans=solve3412();
    if(id==3421)ans=solve3421();
    if(id==4123)ans=solve4123();
    if(id==4132)ans=solve4132();
    if(id==4213)ans=solve4213();
    if(id==4231)ans=solve4231();
    if(id==4312)ans=solve4312();
    if(id==4321)ans=solve4321();
    printf("%lld\n",ans);
}

你可能感兴趣的:(CDOJ 1276 浑身难受 每周一题 div1 树状数组)