Codechef SEAARC Sereja and Arcs (分块、组合计数)
我现在真的什么都不会了呢......
题目链接: https://www.codechef.com/problems/SEAARC
好吧,这题其实考察的是枚举的功力……
题目要求的是\(ABAB\)的数量,这个不太好求,但是不同颜色区间对的总数和\(AABB,ABBA\)的都比较好求
补集转化,求\(ans0,ans1,ans2\), 分别表示总数、\(AABB\)、\(ABBA\)的数量
\(ans0\)很好算
\(ans1\), 枚举\(B\)的左端点
\(ans2\), 分块讨论
若\(A,B\)都是小颜色(该颜色块的数量小于阈值),则枚举\(A\)的左右端点,变成二维数点
若\(A\)是大颜色\(B\)是小颜色,则枚举\(A\)的种类,然后枚举\(B\)的种类和左右端点,推一下式子发现可以维护前缀和省去枚举左端点
若\(B\)是大颜色,同理枚举\(B\)的种类然后枚举\(A\)的种类和左右端点,同样省去枚举左端点
从昨天下午做到今天上午。。
理论最优时间复杂度\(O(n\sqrt{n\log n})\)
代码
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cassert>
#include<vector>
#include<cmath>
#define llong long long
using namespace std;const int N = 1e5;
const int P = 1e9+7;
const llong INV2 = 5e8+4;
int nxt[N+3];
int lstpos[N+3];
int a[N+3];
int num[N+3];
int cnum[N+3];
llong tmp0[N+3],tmp1[N+3],tmp2[N+3];
vector<int> clrpos[N+3];
int n,m,B;
llong ans1,ans2a,ans2b,ans2c,ans0,ans;llong C2(llong x) {return x*(x-1ll)/2ll%P;}
llong update(llong &x,llong y) {x = (x+y)%P;}struct BITree
{llong tr[N+3]; int siz;void addval(int lrb,llong val){while(lrb<=siz){update(tr[lrb],val);lrb += (lrb&(-lrb));}}llong querysum(llong rb){llong ret = 0ll;while(rb){update(ret,tr[rb]);rb -= (rb&(-rb));}return ret;}void clear(){for(int i=0; i<=siz; i++) tr[i] = 0ll;}
} bit1,bit2;void getans0() //ans0=ËùÓÐÑÕÉ«C(num,2)Á½Á½³Ë»ýÖ®ºÍ ²»ËãAAAA
{llong cur = 0ll;for(int i=1; i<=m; i++){llong tmp = C2(num[i]);update(ans0,cur*tmp%P);update(cur,tmp);}
}void getans1() //²»ËãAAAA
{llong tmp = 0ll; //µ±Ç°×ܹ²Í¬É«Çø¼äµÄ¸öÊý for(int i=1; i<=n; i++){update(ans1,(tmp-C2(cnum[a[i]]))*(num[a[i]]-cnum[a[i]]-1)); //ÕâÖÖÑÕÉ«×ܸöÊý¼õÕâ֮ǰµÄ¸öÊý-1£¬µÈÓÚÕâÖ®ºóµÄ¸öÊý£¬³ËÒÔÇ°ÃæµÄÒìÉ«¸öÊý update(tmp,(llong)cnum[a[i]]); //ÕâÖÖÑÕɫ֮ǰµÄ¸öÊý cnum[a[i]]++;}
}void getans2a() //small-small ²»ËãAAAA
{bit1.siz = n; bit1.clear(); llong cur = 0ll;for(int i=1; i<=n; i++) //ö¾ÙÓҶ˵ã {if(num[a[i]]<=B){int tnum = 0;for(int j=nxt[i]; j; j=nxt[j]){llong tmp = cur-bit1.querysum(j)-C2(tnum)+P+P; //>jµÄ×ó¶ËµãµÄ¸öÊý=×ܸöÊý¼õ<=jµÄ¸öÊý£¬È¥µôͬɫµÄ¸öÊý(²»ËãiºÍj)update(ans2a,tmp);tnum++; //ͬɫ¸öÊý }for(int j=nxt[i]; j; j=nxt[j]) //ÓÉÓÚÊÇÓҶ˵ãСÓÚj£¬ÏÈÐ޸ĺó²éѯ {cur++; //Ä¿Ç°Çø¼ä×ܸöÊý,¼´bit1.querysum(i) bit1.addval(j,1);}}}
}void getans2b() //large-small
{for(int i=1; i<=m; i++) //ö¾ÙAÖÖÀà{if(num[i]>B) {tmp1[0] = 0ll; for(int j=1; j<=n; j++) tmp1[j] = tmp1[j-1]+(a[j]==i?1:0);for(int j=1; j<=m; j++) //ö¾ÙBÖÖÀà {if(num[j]<=B){llong cur = 0ll;for(int k=0; k<clrpos[j].size(); k++){int rb = clrpos[j][k];llong tmp = (num[i]-tmp1[rb])*cur%P;update(ans2b,tmp); update(cur,tmp1[rb]); //lb²»¿ÉµÈÓÚrb, ËùÒÔÏȸüÐÂans2bÔÙ¸üÐÂcur }}}}}
}void getans2c() //large-large or small-large ²»ËãAAAA
{for(int i=1; i<=m; i++) //ö¾ÙBµÄÖÖÀà {if(num[i]>B){tmp1[0] = 0; for(int j=1; j<=n; j++) tmp1[j] = tmp1[j-1]+(a[j]==i?1:0);for(int j=1; j<=m; j++) //ö¾ÙAµÄÖÖÀà {if(i==j) continue;llong cur1 = 0ll,cur2 = 0ll;for(int k=0; k<clrpos[j].size(); k++) //ö¾Ùra{//¸üÐÂans2c int ra = clrpos[j][k];llong tmp = tmp1[ra]*tmp1[ra]%P*k%P;update(ans2c,tmp);tmp = tmp1[ra]*(-2ll*cur1-k)%P+P;update(ans2c,tmp);tmp = cur2+cur1+P;update(ans2c,tmp);//¸üÐÂcur1,cur2 update(cur2,tmp1[ra]*tmp1[ra]);update(cur1,tmp1[ra]);}}}}ans2c = ans2c*INV2%P;
}int main()
{scanf("%d",&n); B = sqrt(n)/2;for(int i=1; i<=n; i++) scanf("%d",&a[i]),num[a[i]]++,m = max(m,a[i]),clrpos[a[i]].push_back(i);for(int i=1; i<=n; i++){nxt[i] = lstpos[a[i]];lstpos[a[i]] = i;}getans0();getans1();getans2a();getans2b();getans2c();ans = ((ans0-ans1-ans2a-ans2b-ans2c)%P+P)%P;printf("%lld\n",ans);return 0;
}
Codechef SEAARC Sereja and Arcs (分块、组合计数)相关推荐
- Codechef SEAARC Sereja and Arcs (分块)
我现在真的什么都不会了呢...... 题目链接: https://www.codechef.com/problems/SEAARC 好吧,这题其实考察的是枚举的功力-- 题目要求的是\(ABAB\)的 ...
- 解题报告(五)组合计数(ACM / OI)超高质量题解
繁凡出品的全新系列:解题报告系列 -- 超高质量算法题单,配套我写的超高质量题解和代码,题目难度不一定按照题号排序,我会在每道题后面加上题目难度指数(1∼51 \sim 51∼5),以模板题难度 11 ...
- 解题报告(二)E、(BZOJ3513) [MUTC2013] idiots(生成函数 + FFT + 组合计数)
繁凡出品的全新系列:解题报告系列 -- 超高质量算法题单,配套我写的超高质量题解和代码,题目难度不一定按照题号排序,我会在每道题后面加上题目难度指数(1∼51 \sim 51∼5),以模板题难度 11 ...
- CF1237F Balanced Domino Placements(组合计数,dp)
CF1237F Balanced Domino Placements Solution 显然可以先考虑横着的骨牌,再考虑竖着的骨牌.但是思路卡在了选取横着的骨牌会对竖着的骨牌的相邻对数产生影响. 然而 ...
- 【Luogu4921】情侣?给我烧了!(组合计数)
[Luogu4921]情侣?给我烧了!(组合计数) 题面 洛谷 题解 很有意思的一道题目. 直接容斥?怎么样都要一个平方复杂度了. 既然是恰好\(k\)对,那么我们直接来做: 首先枚举\(k\)对人出 ...
- 1307 牡牛和牝牛(组合计数-递推)
1. 问题描述: 约翰要带 N 只牛去参加集会里的展示活动,这些牛可以是牡牛,也可以是牝牛.牛们要站成一排,但是牡牛是好斗的,为了避免牡牛闹出乱子,约翰决定任意两只牡牛之间至少要有 K 只牝牛.请计算 ...
- 学组合数学心得与题解(一)——组合计数
今天我在某网站上稍微学习了一下组合数学,准确来讲,今天就看了看组合计数.像一些弱智的排列数.组合数大家肯定在小学奥数就已经精通了(只有我这种蒟蒻忘的精光).当然,博主比较菜,连二项式定理.帕斯卡恒等式 ...
- 基础组合计数常用的概念和方法总结
基础组合计数常用的概念和方法总结 一.组合计数中的基本概念与性质 1.排列 定义 性质 2.组合 定义 性质 二.组合计数中的一些常用技巧 1.容斥原理 定义 公式 2.捆绑与插空法 捆绑法 插空法 ...
- 数学知识——组合计数
组合计数 文章目录 组合计数 概述 动态规划 牡牛和牝牛 思路 代码 隔板法 方程的解 思路 代码 序列统计 思路 代码 加法 & 乘法原理 加法原理 乘法原理 车的摆放 思路 代码 容斥原理 ...
最新文章
- matlabpython建模_一直在用Matlab建模,现在Python很火,用学么?
- boost::local_time模块实现创建各种dst_calc_rule的测试程序
- 二分图最大权匹配算法KM
- AI会率先在汽车、安全和金融领域落地!不服来辩 | AI科技评论
- html仿qq最小化怎么实现,JS仿QQ好友列表展开、收缩功能(第一篇)
- PPT图片模板等素材打包下载
- 樊登读书赋能读后感_一场人均4万元的知识盛宴,樊登直播首秀到底讲了什么?...
- PRML 回归的线性模型
- 蓝牙路由器系列产品:企业级Cassia E1000
- 计算机与电气工程sci期刊,2019年电气工程领域的英文SCI期刊(影响因子+近年来期刊发表数量)...
- 高清录播系统与流媒体服务器,校园高清一体式高清录播系统教学录播跟踪网络直播...
- 网站修改了文档html默认保存路径,我在网页上打开word文档修改后就直接保存了 请问他的保存路径在哪???...
- 从辣条国家标准到 java 接口规范
- 基于ArcGIS Pro 的AI地图配色工具
- 机器人教育对孩子们的作用
- android换手机照片怎么转移,换手机了怎么把照片转移到新手机
- 大数据和java就业前景_Java大数据应用领域及就业方向
- Ubuntu下噩梦搬的hud-service进程CPU直接爆炸
- 剑指Offer——编程题的Java实现
- CORBA协议相关的概念
热门文章
- 吴恩达《神经网络与深度学习》精炼笔记(5)-- 深层神经网络
- Coursera吴恩达《卷积神经网络》课程笔记(4)-- 人脸识别与神经风格迁移
- 解决Downloading data from https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz国内下载速度缓慢的问题
- PHP中的else怎么用,php中ifelse与elseif使用区别实例介绍
- python numpy 子数组_Python快速转换numpy数组中Nan和Inf的方法实例说明
- 新型机器学习算法:正则化理解
- AlexNet结构详解(引用MrGiovanni博士)
- 如何使用SQL Server INSTEAD-OF触发器
- 用Python画一只蝙蝠
- c语言一整行一整行读取文件