Codeforces 878 E. Numbers on the blackboard

解题思路

有一种最优策略是每次选择最后面一个大于等于 \(0\) 的元素进行合并,这样做完以后相当于给这个元素乘 \(2\) ,并且不使前面一个元素的值增加了。但是按照这样的策略做不太好维护,考虑做完以后有许多块,除了第一个块以外每一个块都是负的,然后将这些块与第一个块合并。那么用并查集维护一下每个块,每一个元素被乘 \(2\) 的次数就是这个块里面位置比它小的元素个数。定义一个块的和为每个元素乘上其对应系数的和,对于一组询问,答案就是第一块的和加上 \(2\times\) 其它块的和。

考虑怎么解决多组询问,将询问离线下来,对于每一个右端点 \(r_i\) ,如果询问的 \(l_i=1\) ,那么答案就是第一块的和加上 \(2\times\) 其它块的和。否则找到 \(l_i\) 所在的块,这个块以 \(l_i\) 开头的后缀是对于这一询问的"第一个块",因为这个后缀任意时刻是非负的,所以这个后缀的块和就是从右到左直接合并的答案。那么只要维护一下块的前缀和以及一段区间进行从右到左直接合并的答案就好了。

感觉写的非常意识流,多手玩手玩就好了。

code

/*program by mangoyang*/
#include <bits/stdc++.h>
#pragma GCC optimize("Ofast", "inline")
#define inf (0x7f7f7f7f)
#define Max(a, b) ((a) > (b) ? (a) : (b))
#define Min(a, b) ((a) < (b) ? (a) : (b))
typedef long long ll;
using namespace std;
template <class T>
inline void read(T &x){
int ch = 0, f = 0; x = 0;
for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = 1;
for(; isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;
if(f) x = -x;
}
const int N = 1000005, mod = 1e9 + 7;
vector<pair<int, int> > Q[N];
int sz[N], sum[N], s[N], s2[N], ss[N], pw[N], fa[N], a[N], ans[N], n, q;
inline void up(int &x, int y){
x = x + y >= mod ? x + y - mod : x + y;
}
inline int Pow(int a, int b){
int ans = 1;
for(; b; b >>= 1, a = 1ll * a * a % mod)
if(b & 1) ans = 1ll * ans * a % mod;
return ans;
}
inline int ask(int x){
return x == fa[x] ? x : fa[x] = ask(fa[x]);
}
inline void unite(int x, int y){
int p = ask(x), q = ask(y);
if((sz[p] >= 30 && s[q]) || s[p] + (1ll * s[q] << sz[p]) >= mod) s[p] = mod;
else s[p] = s[p] + (1ll * s[q] << sz[p]);
up(s2[p], 1ll * s2[q] * pw[sz[p]] % mod);
fa[q] = p, sz[p] += sz[q];
}
inline int find(int x, int lim){
int l = 1, r = lim, res = lim + 1;
while(l <= r){
int mid = (l + r) >> 1;
if(ask(mid) > x) res = mid, r = mid - 1;
else l = mid + 1;
}
return res;
}
inline int gao(int x, int y){
return 1ll * (ss[y] - ss[x-1] + mod) % mod * Pow(Pow(2, x), mod - 2) % mod;
}
signed main(){
read(n), read(q), pw[0] = 1;
for(int i = 1; i <= n; i++){
read(a[i]), fa[i] = i, sz[i] = 1;
s[i] = a[i], s2[i] = (a[i] + mod) % mod;
pw[i] = 2ll * pw[i-1] % mod;
ss[i] = (ss[i-1] + 1ll * pw[i] * s2[i] % mod) % mod;
}
for(int i = 1, x, y; i <= q; i++)
read(x), read(y), Q[y].push_back(make_pair(x, i));
for(int i = 1; i <= n; i++){
while(s[ask(i)] >= 0 && ask(i) > 1) unite(ask(i) - 1, i);
sum[ask(i)] = (sum[ask(ask(i)-1)] + 2ll * s2[ask(i)] % mod) % mod;
for(int j = 0; j < (int) Q[i].size(); j++){
int x = Q[i][j].first, y = find(x, i);
int res = (sum[ask(i)] - sum[ask(y-1)] + mod) % mod;
ans[Q[i][j].second] = (res + gao(x, y - 1)) % mod;
}
}
for(int i = 1; i <= q; i++) printf("%d\n", ans[i]);
return 0;
}

Codeforces 878 E. Numbers on the blackboard的更多相关文章

  1. CodeForces 55D "Beautiful numbers"(数位DP+离散化处理)

    传送门 参考资料: [1]:CodeForces 55D Beautiful numbers(数位dp&&离散化) 我的理解: 起初,我先定义一个三维数组 dp[ i ][ j ][ ...

  2. 【CF878E】Numbers on the blackboard 并查集

    [CF878E]Numbers on the blackboard 题意:给你一个长度为n个数列,你每次可以进行如下操作: 选取两个相邻的数x,y(x在y左面),然后将这两个数去掉,用x+2y替换它. ...

  3. Codeforces 55D. Beautiful numbers(数位DP,离散化)

    Codeforces 55D. Beautiful numbers 题意 求[L,R]区间内有多少个数满足:该数能被其每一位数字都整除(如12,24,15等). 思路 一开始以为是数位DP的水题,觉得 ...

  4. CF 878E Numbers on the blackboard 并查集 离线 贪心

    LINK:Numbers on the blackboard 看完题觉得很难. 想了一会发现有点水 又想了一下发现有点困难. 最终想到了 但是实现的时候 也很难. 先观察题目中的这个形式 使得前后两个 ...

  5. CodeForces 151B Phone Numbers

     Phone Numbers Time Limit:2000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u Sub ...

  6. codeforces 55D - Beautiful numbers(数位DP+离散化)

    D. Beautiful numbers time limit per test 4 seconds memory limit per test 256 megabytes input standar ...

  7. Codeforces 165E Compatible Numbers(二进制+逆序枚举)

    E. Compatible Numbers time limit per test 4 seconds memory limit per test 256 megabytes input standa ...

  8. codeforces Gym 100338E Numbers (贪心,实现)

    题目:http://codeforces.com/gym/100338/attachments 贪心,每次枚举10的i次幂,除k后取余数r在用k-r补在10的幂上作为候选答案. #include< ...

  9. CodeForces 165E Compatible Numbers(位运算 + 好题)

    wo integers x and y are compatible, if the result of their bitwise "AND" equals zero, that ...

随机推荐

  1. ECharts将折线变平滑和去掉点的属性(转载)曲线变圆滑

    本文链接:https://blog.csdn.net/sinat_36422236/article/details/62430114 series : [ { name:'your name', sy ...

  2. django_restframework项目之python虚拟环境配置(一)

    虚拟环境的搭建 优点 1.使不同应用开发环境相互独立 2.环境升级不影响其他应用,也不会影响全局的python环境 3.防止出现包管理混乱及包版本冲突 windows 安装 # 建议使用pip3安装到 ...

  3. 安装Ubuntu后需要做的事

    卸载软件 纸牌 麻将 扫雷 数独 火狐 邮件 扫描 拍照 照片 视频 计划 日历 打印 备份 计算器 亚马逊 电源统计 音乐播放 远程桌面 To Do LibreOffice 换下载源 装机的时候下载 ...

  4. Nginx Rewrite相关功能-防盗链

    Nginx Rewrite相关功能-防盗链 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任.

  5. CentOS7配置本地Yum源

    从CentOS7官网下载DVD中存在需要的大部分软件,所以在没有网络的情况下可以配置yum源为本地的DVD,下载速度快,软件稳定.1. 如果使用虚拟机,那么就在虚拟机中挂载DVD的iso文件.2. 使 ...

  6. RMP和YUM软件安装

    1.卸载RPM包 rpm -e rpm包的名称 2.安装rpm包 rmp -ivh xxx.rpm 3.查询yum服务器是否有需要安装的软件 yum list|grep xxx软件列表 4.yum安装 ...

  7. func_get_args call_user_func_array

    <?php //call_user_func_array.php function test($arg1,$arg2) { $t_args = func_get_args(); $t_resul ...

  8. CentOS7 开放端口 通过 firewall-cmd 工具来操作防火墙

    CentOS7 提供了 firewall-cmd 工具来操作防火墙. firewall-cmd --permanent:表示设置为持久,配置被写入配置文件,跨重启,不会立即生效,重新加载配置后生效.不 ...

  9. python nose测试框架全面介绍十三 ---怎么写nose插件

    之前有一篇文章介绍了自己写的插件 nose进度插件,但最近有朋友问我,看着nose的官方文档写的插件没用,下面再详细介绍一下 一.准备 1.新建一个文件夹,随便文件夹的名字,假设文件夹放在f://aa ...

  10. USACO Slowing down

    洛谷 P2982 [USACO10FEB]慢下来Slowing down 洛谷传送门 JDOJ 2684: USACO 2010 Feb Gold 3.Slowing down JDOJ传送门 Des ...