[CTSC2008]图腾totem

[CTSC2008]图腾totem

Time Limit:30000MS  Memory Limit:165536K
Total Submit:31 Accepted:9
Case Time Limit:4000MS

Description

在完成了古越州圆盘密码的研究之后,考古学家小布来到了南美大陆的西部。相传很久以前在这片土地上生活着两个部落,一个部落崇拜闪电,另一个部落崇拜高 山,他们分别用闪电和山峰的形状作为各自部落的图腾。
小布的团队在山洞里发现了一幅巨大的壁画,壁画上被标记出了N个点,经测量发现这N个点的水平位置和竖直位置是两两不同的。小布认为这幅壁画所包 含的信息仅与这N个点的相对位置有关,因此不妨设坐标分别为(1, y1) , (2, y2), …, (n, yn),其中y1~yn是1~N的一个排列。
小布的团队打算研究在这幅壁画中包含着多少个图腾,其中闪电图腾的定义图示如下(图腾的形式只与4个纵坐标值的相对大小排列顺序有关):

崇拜高山的部落有两个氏族,因而山峰图腾有如下两种形式,左边为A类,右边为B类(同样,图腾的形式也都只与4个纵坐标值的大小排列顺序有关):

小布的团队希望知道,这N个点中两个部落图腾数目的差值。因此在本题中,你需要帮助小布的团队编写一个程序,计算闪电图腾数目减去山峰图腾数目的 值,由于该值可能绝对值较大,本题中只需输出该值对16777216的余数(注意余数必为正值,例如-1对16777216的余数为16777215)。

Input

第一行包含一个整数N,为点的数目。
接下来一行包含N个整数,分别为y1, y2, …, yn。保证y1, y2, …, yn是1~N的一个排列。

Output

仅包含一个数,表示闪电图腾数目与山峰图腾数目的差值对16777216的余数。

Sample Input

【样例输入一】
5
1 5 3 2 4
【样例输入二】
4
1 2 4 3

Sample Output

【样例输出一】
0

【样例输出二】
16777215

Hint

样例一中共有1个闪电图腾(1324)和1个B类山峰图腾(1532)。
样例二中仅有一个A类山峰图腾(1243),故差值为-1,答案为16777215。
【数据规模】
对于10%的数据,N ≤ 600;
对于40%的数据,N ≤ 5000;
对于100%的数据,N ≤ 200000。

Source

哇咔咔。。居然让我A掉了这题。。。
先谢国家。。
再谢gyz神牛和nzk神牛。。。
设f(xxxx)表示排序xxx出现的数量。。
那么我们要求的是f(1324)-f(1243)-f(1432)
注意到f(1243)=f(12xx)-f(1234)。。这两个都很好求。。所以1243解决了。。
但其他两个几乎不可做啊。。题目既然让我们相减,这两个式子必然是有所关联的。。
f(1324)-f(1432)
我们尝试着在两边都+上一个f。。
(f(1324)+f(1423))-(f(1432)+f(1423))
=
f(1x2x)-f(14xx)
这两个都是线段树可做的。。所以问题就解决了。。。
1x2x的做法是把所有数字从小到大加入序列。。
当加入数字x的时候,没有加入的就是空白,它一定比x大
对每个数字维护它后面的空白数量。
然后维护子段和。。
考虑当前加入的数字为2就差不多了。。

14xx的做法来自nzk
吧所有数字从左到右加入按大小组成的序列。。。
那么考虑当前的数字为4.。那么xx必然是它和1之间的空白。。
那么维护每个数字后面的空白数量,的空白的数量的平方
并对这两个进行子段和的维护。。。。
就差不多了囧。。。
代码见网盘。。

9 thoughts on “[CTSC2008]图腾totem

  1. 贴代码一段,果断不解释#include <stdio.h>int a[200001],p[200001],x[6][200001],n,i,t,r,z,s;I(int a,int i,int s){for (;i<=n;i+=i&-i)x[a][i]+=s;}S(int a,int i){s=0;for (;i;i-=i&-i)s+=x[a][i];return s;}main(){scanf(“%d”,&n);for (i=1;i<=n;i++){scanf(“%d”,&a[i]);p[a[i]]=i;t=S(0,a[i]);r=n-a[i]-i+t+1;z+=S(2,a[i])-r*(r-1LL)*(r-2)/6+r*(t*a[i]-S(3,a[i])-t*(t+1LL)/2);I(2,a[i],S(1,a[i]));I(1,a[i],S(0,a[i]));I(0,a[i],1);I(3,a[i],a[i]);}for (i=1;i<=n;i++){t=S(4,p[i]);z+=(t*p[i]-S(5,p[i])-t*(t+1LL)/2)*(n-p[i]-i+t+1);I(4,p[i],1);I(5,p[i],p[i]);}printf(“%d”,z&16777215);}

Leave a Reply to WJBZBMR Cancel reply

Your email address will not be published. Required fields are marked *