NKOI 3724 图腾
2016-07-21 20:26
330 查看
[CTSC2008]图腾totem
2014年12月2日1,3203Description
在完成了古越州圆盘密码的研究之后,考古学家小布来到了南美大陆的西部。相传很久以前在这片土地上生活着两个部落,一个部落崇拜闪电,另一个部落崇拜高山,他们分别用闪电和山峰的形状作为各自部落的图腾。小布的团队在山洞里发现了一幅巨大的壁画,壁画上被标记出了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。
我们用****表示一种结构的方案数。
显然题目要求的是 1324-1432-1243=(1*2*-1423)-(14**-1423)-(12**-1234)
=1*2*-14**-12**+1234
=1*2*-(1***-13**)+1234
=1*2*-1***+13**+1234
所以我们只要求出来1*2*,1***,13***,1234的方案数就好了。
先求出l[i],r[i]表示在i的左/右,比a[i]小的个数
可以先用树状数组求l[i],则r[i]=(a[i]-l[i]-1)
———————————————————————————————————
f[1xxx]
枚举(1)的位置i,则i右边比i大的数有n-i-r[i],设为t
则xxx的方案数为t*(t-1)*(t-2)/6(组合数化简后结果)
———————————————————————————————————
f[1234]
枚举(3)的位置i,则(4)的个数有n-i-r[i]
12的对数为sigma(l[j]) (a[j]<a[i],j<=i)
两式相乘法
———————————————————————————————————
f[1x2x]
枚举(2)的位置i,则(2)左边的【数字对】(a[x],a[y])(a[x]<a[i],y任意)有l[i]*(i-1)个
但只有a[y]>a[i],且y>x的合法
多算的有两部分,一部分是a[y]<a[i],y>x,另一部分y<x
第一部分l[i]*(l[i]-1)/2,第二部分为sigma j (a[j]<a[i])
———————————————————————————————————
f[13xx]
枚举(3)的位置i,(3)的右侧要是(2)(4)或者(4)(2)
(4)的个数n-i-r[i]
则【数字对】(a[x],a[y])(a[x]<a[i],x<i,a[y]<a[i])有l[i]*(a[i]-1)个
但只有a[x]<a[y],y>i的合法
也多算了两部分,一部分是x<y<i,形如123,另一部分是a[x]<a[y],y<x,形如213
第一部分l[i]*(l[i]-1)/2 第二部分sigma a[j] (a[j]<a[i])
以上就是这道题的题解了,据说这还是当时比赛最弱鸡的一道题,然而让我爽了一个多小时
还有一个要注意的地方,就是取mod的时候要把mod看做一个常数,并且将%符号改为&,这样才能让题目中负数的取模得到正确答案
#include<iostream> #include<cstdio> #include<cstring> #define LL long long #define lowbit(x) x&(-x) #define mod 16777215 using namespace std; const int maxn=200005; int n,sum,a[maxn]; LL l[maxn],r[maxn],c[maxn]; inline void _read(int &x){ char t=getchar();bool sign=true; while(t<'0'||t>'9') {if(t=='-')sign=false;t=getchar();} for(x=0;t>='0'&&t<='9';t=getchar())x=x*10+t-'0'; if(!sign)x=-x; } void modify(int x,int d){for(int i=x;i<=n;i+=lowbit(i))c[i]+=d;} LL getsum(int x){ LL sum=0; for(int i=x;i;i-=lowbit(i))sum+=c[i]; return sum; } int work1(){ memset(c,0,sizeof(c)); LL sum=0; for(int i=1;i<=n;i++){ LL w=n-i-r[i]; if(w>=3)sum=(sum+w*(w-1)*(w-2)/6)&mod; } return sum; } int work2(){ memset(c,0,sizeof(c)); LL sum=0; for(int i=1;i<=n;i++){ sum=(sum+getsum(a[i])*(n-i-r[i]))&mod; modify(a[i],l[i]); } return sum; } int work3(){ memset(c,0,sizeof(c)); LL sum=0; for(int i=n;i;i--){ sum=(sum+(getsum(a[i])-r[i]*(r[i]+1)/2)*(n-r[i]-i))&mod; modify(a[i],a[i]); } return sum; } int work4(){ memset(c,0,sizeof(c)); LL sum=0; for(int i=1;i<=n;i++){ sum=(sum+(l[i]*(i-1)-getsum(a[i])-l[i]*(l[i]-1)/2)*(n-r[i]-i))&mod; modify(a[i],i); } return sum; } int main(){ _read(n); int i; for(i=1;i<=n;i++){ _read(a[i]); l[i]=getsum(a[i]); r[i]=a[i]-l[i]-1; modify(a[i],1); } printf("%d",(work2()+work3()+work4()-work1())&mod); }
相关文章推荐
- 百度工程师讲PHP函数的实现原理及性能分析(一)
- java设计模式之适配器模式
- boost 1.56.0 编译及使用
- 使用 foreach 操作数组
- 范式
- Android Studio里引入别的project作为库
- PHP 引入并读取php数据文件,改html后缀为php完成html的一次编写ul,li遍历出现多次li
- 消息队列的流派之争
- HDD is Outdated Technology
- Android 中打开相册图片 使用相机拍摄并存储照片
- socket accept后的fd是否占用新端口
- 日常生活
- 一个小面试题sql
- Symmetric Tree
- Android_实现获取手机内apk并分享的功能
- 【CodeForces】610A - Pasha and Stick(水)
- 机器学习实战 - 读书笔记(07) - 利用AdaBoost元算法提高分类性能
- HDU 1312 Red and Black 红与黑 搜索 dfs bfs
- 嵌入式系统上C++调用C语言接口代码链接时找不到C函数问题处理
- Andriod File 路径转换为Uri