我现在真的什么都不会了呢......

题目链接: 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 (分块)相关推荐

  1. Codechef SEAARC Sereja and Arcs (分块、组合计数)

    我现在真的什么都不会了呢...... 题目链接: https://www.codechef.com/problems/SEAARC 好吧,这题其实考察的是枚举的功力-- 题目要求的是\(ABAB\)的 ...

  2. 【CODECHEF】Children Trips(分块)

    主要的操作是:每一天走到最远能够走到的休息区 确实一开始没有想到是分块,只是觉得1<=d<=21<=d<=21<=d<=2有点东西,但是没有搞出来. 其实也可以说是 ...

  3. 锦标赛排序、洪水填充算法、平衡规划

    锦标赛排序 锦标赛排序(胜者树,记录胜者) 锦标赛排序(胜者树,记录胜者) - Class Xman - 博客园 锦标赛排序(胜者树,记录胜者)_继续微笑lsj-CSDN博客_锦标赛排序 数据结构之树 ...

  4. 解题报告(二)多项式问题(多项式乘法及其各种运算)(ACM/ OI)超高质量题解

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 繁凡出品的全新系列:解题报告系列 -- 超高质量算法题单,配套我写的超高质量的题解和代码,题目难度不一 ...

  5. Codechef TRIPS Children Trips (分块、倍增)

    题目链接: https://www.codechef.com/problems/TRIPS 感觉CC有点毒瘤啊.. 题解: 首先有一个性质可能是因为太傻所以网上没人解释,然而我看了半天: 就是正序和倒 ...

  6. BZOJ3509 [CodeChef] COUNTARI 【分块 + fft】

    题目链接 BZOJ3509 题解 化一下式子,就是 \[2A[j] = A[i] + A[k]\] 所以我们对一个位置两边的数构成的生成函数相乘即可 但是由于这样做是\(O(n^2logn)\)的,我 ...

  7. CodeChef Chef and Churu [分块]

    题意: 单点修改$a$ 询问$a$的区间和$f$的区间和 原来普通计算机是这道题改编的吧... 对$f$分块,预处理$c[i][j]$为块i中$a_j$出现几次,$O(NH(N))$,只要每个块差分加 ...

  8. 一二三系列之CodeChef分块——Chef and Churu,Chef and Problems,Children Trips

    文章目录 Chef and Churu source solution code Chef and Problems source solution code Children Trips sourc ...

  9. Codechef :Children Trips/TRIPS(树分块)

    传送门 题解: 设一个阀值 k k k,小于 k k k的倍增,大于 k k k的暴力跳,这样的复杂度是 O ( n m k + n k ) O(\frac{nm}{k}+nk) O(knm​+nk) ...

最新文章

  1. 盘点热门的目标检测开源方案(附论文+代码下载)
  2. 课后作业-阅读任务-阅读提问-3 。
  3. HTML语言基础.上
  4. 异构网络垂直切换算法lte/wimax
  5. 约瑟夫问题(丢手帕问题)的java实现
  6. ffmpeg 参数_使用FFMPEG进行视频转码
  7. 如何检测python是否安装_布同自制Python函数帮助查询小工具
  8. 监控组策略应用----组策略结果
  9. 面向接口的开发到面向对象的编程
  10. paip.c++ 进程间通信方法大总结
  11. 1.7 COMS边沿触发器
  12. MYSQL 视图 触发器 存储过程 事务 索引
  13. Linux CentOS 7 多网卡配置bond模式 bond1 bond5 bond6
  14. CSDN日报20170317——《转行穷三年?未必!》
  15. holder.js如何使用
  16. 初探微信摇一摇周边与iBeacon
  17. < Linux > 守护进程
  18. 求数组排序后相邻数的最大差值
  19. 羊了个羊游戏h5网页版源码
  20. linux下的pmap命令

热门文章

  1. 第16课:项目实战——利用 PyTorch 构建 CNN 模型
  2. java获取异常的数据_Java(8题):异常,通过try catch进行处理,登录,商品,使用jdbc进行读取,详细图析...
  3. 返回值类型与函数类型不匹配_C++返回值类型后置(跟踪返回值类型)
  4. VTK修炼之道54:图形基本操作进阶_表面重建技术(三角剖分)
  5. 手动配置WCF宿主的.config文件遇到的几种错误
  6. 关于Delphi中TRttiContext.FindType失效的问题
  7. 对“js变量作用域的疑问”的解答
  8. enum-使用宏管理你的枚举型数据
  9. 有时候明明没有问题的程序为什么通不过?
  10. main() 函数解析(一)——Linux-0.11 剖析笔记(六)