1. 程式人生 > >[CTSC2008]圖騰

[CTSC2008]圖騰

傳送門

雖然是遠古時期的ctsc,但是果然還是ctsc啊

前置芝士:樹狀陣列

這個題最開始的思路很好想,由於之前寫過一個類似處理的題,所以這個題我一開始就想到了思路。

首先,我們可以嘗試講圖騰表示為xxxx的形式

那麼閃電就是:1324;高山是:1243和1432

ans=1324-1243-1432

然後應該容斥一下,但是我不會了。。

瞄一眼題解,我成功吧那個式子容斥出來了。

ans=1324-1243-1432

ans=(1x2x-1423)-(14xx-1423)-(12xx-1234)

ans=1x2x-14xx-12xx+1234

ans=1x2x-1xxx+13xx+1234

然後我就震驚的發現,我又不會了,這次變成仔細的研究題解了,各種討論情況啊,nb啊,大佬們

下面的討論情況還是看洛谷題解的吧,太難寫了。題解傳送門

程式碼:

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
void read(int &x) {
    char ch; bool ok;
    for(ok=0,ch=getchar(); !isdigit(ch); ch=getchar()) if(ch=='-') ok=1;
    for(x=0; isdigit(ch); x=x*10+ch-'0',ch=getchar()); if(ok) x=-x;
}
#define rg register
#define lowbit(i) (i&(-i))
#define ls (get(a[i]))
#define rs (a[i]-1-ls)
#define lb (i-1-l[i])
#define rb (n-i-r[i])
const int mod=16777216,maxn=2e5+1;
int n,ans,a[maxn],f[maxn],now,l[maxn],r[maxn];
void add(int x,int y){for(rg int i=x;i<=n;i+=lowbit(i))(f[i]+=y)%=mod;}
int get(int x){int ans=0;for(rg int i=x;i;i-=lowbit(i))ans+=f[i];return ans;}
int C(int n,int m){return 1ll*n*(n-1)*(n-2)/6%mod;}
int main()
{
    read(n);
    for(rg int i=1;i<=n;i++)read(a[i]),l[i]=ls,r[i]=a[i]-1-l[i],add(a[i],1);
    memset(f,0,sizeof f);
    for(rg int i=1;i<=n;i++)
    {
        ans=((ans+(l[i]*(i-1)-get(a[i])-l[i]*(l[i]-1)/2)*rb)%mod+mod)%mod,
        ans=((ans-C(rb,3))%mod+mod)%mod;
        add(a[i],i);
    }
    memset(f,0,sizeof f);
    for(rg int i=n;i;i--)ans=((ans+(1ll*get(a[i])-1ll*r[i]*(r[i]-1)/2)*rb)%mod+mod)%mod,add(a[i],a[i]-1);
    memset(f,0,sizeof f);now=0;
    for(rg int i=1;i<=n;i++)ans=(ans+1ll*rb*get(a[i]))%mod,add(a[i],l[i]);
    printf("%d\n",ans);
}