Description

给出一个长度为n的序列a和一个整数p

有m组询问,每组询问给出一个区间\([l,r]\)

你需要给出下面这个过程的结果

ans = 0
for i from l to r
{
ans = ans + a[i]
if ans > p then ans = ans - p;
}
return ans

\(n\leq 10^6\)

\(m<=2\times10^5\)

\(p\leq10^9\)

\(-10^9\leq a_i\leq10^9\)

Solution

显然一个区间内至多只会减区间长度次p

也就是说如果我们设一个函数\(f(x)\)为初始为x,经过区间\([l,r]\)后的答案,那么\(f(x)\)显然由\(r-l+2\)段斜率为1的一次函数构成,且相邻两段之间截距差为p

更进一步的,可以发现每一段的长度是\(O(p)\)的

那么我们可以考虑用线段树维护函数,对于每个线段树区间记下每段的端点,查询很简单,直接从0开始加上这一段的贡献,并在下一个区间中二分属于那一段即可。

关键是建树

考虑左子区间和右子区间已经建好,考虑将它们合并,实际上就是一个函数复合的过程。

具体实现来说,枚举左子区间的所有段,计算出相应的值域区间,然后右边用一个指针找合法的右段。

由于每一段的长度均为\(O(p)\),因此每次指针动的位置数是常数级的。

总的时间复杂度为\(O(n\log n+m\log^2 n)\)

可以参考程序。

Code

//Copyright Reserved by BAJim_H
#include <bits/stdc++.h>
#define fo(i,a,b) for(int i=a;i<=b;++i)
#define fod(i,a,b) for(int i=a;i>=b;--i)
typedef long long LL;
const int N=2000005;
const LL INF=(LL)1e16;
using namespace std;
vector<LL> f[N];
int t[N][2],d[200],a[N],n,n1,mo,q;
LL sm[N];
template <class I>
void read(I &x)
{
x=0;char ch=getchar();I v=1;
while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
if(ch=='-') v=-1,ch=getchar();
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
x=x*v;
}
void build(int k,int l,int r)
{
if(l==r) {f[k].push_back(-INF),f[k].push_back(mo-a[l]);sm[k]=a[l];return;}
int mid=(l+r)>>1;
t[k][0]=++n1,build(t[k][0],l,mid);
t[k][1]=++n1,build(t[k][1],mid+1,r);
int x=t[k][0],y=t[k][1],rx=f[x].size(),ry=f[y].size();
f[k].resize(rx+ry-1,INF);
for(int i=0,j=0;i<rx;++i)
{
LL xl=f[x][i],xr=(i+1!=rx)?f[x][i+1]-1:INF,yl=xl+sm[x]-(LL)i*mo,yr=xr+sm[x]-(LL)i*mo;
while(j>0&&f[y][j]>yl) j--;
while(j<ry&&f[y][j]<=yl) j++;
if(j) j--;
while(j<ry&&f[y][j]<=yr) f[k][i+j]=min(f[k][i+j],max(xl,f[y][j]-sm[x]+(LL)i*mo)),j++;
}
f[k][0]=-INF;
sm[k]=sm[t[k][0]]+sm[t[k][1]];
}
void find(int k,int l,int r,int x,int y)
{
if(x<=l&&r<=y) {d[++d[0]]=k;return;}
int mid=(l+r)>>1;
if(x<=mid) find(t[k][0],l,mid,x,y);
if(y>mid) find(t[k][1],mid+1,r,x,y);
}
LL query(int x,int y)
{
d[0]=0;find(1,1,n,x,y);
LL c=0;
fo(i,1,d[0])
c+=sm[d[i]]-(LL)mo*(upper_bound(f[d[i]].begin(),f[d[i]].end(),c)-f[d[i]].begin()-1);
return c;
}
int main()
{
cin>>n>>q>>mo;
fo(i,1,n) read(a[i]);
n1=1;
build(1,1,n);
fo(i,1,q)
{
int x,y;
read(x),read(y);
printf("%lld\n",query(x,y));
}
}

【杂题】[CodeForces 1172F] Nauuo and Bug【数据结构】【线段树】的更多相关文章

  1. Codeforces 1172F Nauuo and Bug [线段树]

    Codeforces 思路 定义\(f_{l,r}(x)\)表示数\(x\)从\(l\)进去\(r\)出来的时候会变成什么样子.容易发现这个函数是个分段函数,每一段都是斜率为1的一次函数,并且段数就是 ...

  2. [Codeforces 266E]More Queries to Array...(线段树+二项式定理)

    [Codeforces 266E]More Queries to Array...(线段树+二项式定理) 题面 维护一个长度为\(n\)的序列\(a\),\(m\)个操作 区间赋值为\(x\) 查询\ ...

  3. [Codeforces 280D]k-Maximum Subsequence Sum(线段树)

    [Codeforces 280D]k-Maximum Subsequence Sum(线段树) 题面 给出一个序列,序列里面的数有正有负,有两种操作 1.单点修改 2.区间查询,在区间中选出至多k个不 ...

  4. codeforces 1217E E. Sum Queries? (线段树

    codeforces 1217E E. Sum Queries? (线段树 传送门:https://codeforces.com/contest/1217/problem/E 题意: n个数,m次询问 ...

  5. codeforces 339C Xenia and Bit Operations(线段树水题)

    转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud Xenia and Bit Operations Xenia the beginn ...

  6. Codeforces 1045. A. Last chance(网络流 + 线段树优化建边)

    题意 给你 \(n\) 个武器,\(m\) 个敌人,问你最多消灭多少个敌人,并输出方案. 总共有三种武器. SQL 火箭 - 能消灭给你集合中的一个敌人 \(\sum |S| \le 100000\) ...

  7. Codeforces 446C DZY Loves Fibonacci Numbers [线段树,数论]

    洛谷 Codeforces 思路 这题知道结论就是水题,不知道就是神仙题-- 斐波那契数有这样一个性质:\(f_{n+m}=f_{n+1}f_m+f_{n}f_{m-1}\). 至于怎么证明嘛-- 即 ...

  8. Codeforces 903G Yet Another Maxflow Problem - 线段树

    题目传送门 传送门I 传送门II 传送门III 题目大意 给定一个网络.网络分为$A$,$B$两个部分,每边各有$n$个点.对于$A_{i} \ (1\leqslant i < n)$会向$A_ ...

  9. Codeforces 1107G Vasya and Maximum Profit 线段树最大子段和 + 单调栈

    Codeforces 1107G 线段树最大子段和 + 单调栈 G. Vasya and Maximum Profit Description: Vasya got really tired of t ...

随机推荐

  1. Idea导入Eclipse的Web项目并部署到Tomcat

    ⒈启动Idea,选择导入项目 选择导入的项目路径后,选择项目类型后一路next即可. ⒉选择File->Project Structure打开项目配置窗口(ctrl + alt + shift ...

  2. opencv学习之读取图像-imread函数

    序 想要完整全面地学习opencv,仅凭阅读samples的示例源码是不够的.毕竟opencv是一个拥有非常多函数的程序库,所以在每学习一个函数时,芒果觉得有必要记录下来,分享给有需要的同学.于是,就 ...

  3. Threadlocal线程本地变量理解

    转载:https://www.cnblogs.com/chengxiao/p/6152824.html 总结: 作用:ThreadLocal 线程本地变量,可用于分布式项目的日志追踪 用法:在切面中生 ...

  4. 使用jdbc操作ClickHouse

    使用jdbc操作ClickHouse 2018年07月01日 01:33:00 狮子头儿 阅读数 10501   版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处 ...

  5. ELK电子书籍

    Elasticsearch in Action(英文版).pdfElasticsearch实战 in action(中文版).pdfElasticsearch技术解析与实战.pdfElasticsea ...

  6. 重学HTML5的语义化

    干了这么多年的前端,之前面试的时候经常会遇到面试官提问:你是如何理解HTML的语义化的? 说实话,之前遇到这个问题的时候,都是从网上找参考答案,然后记下来,用自己的语言重新组织一下,就变成自己的理解了 ...

  7. Django框架——基础之路由系统(urls.py)

    1.URL路由系统前言 URL是Web服务的入口,用户通过浏览器发送过来的任何请求,都是发送到一个指定的URL地址,然后被响应. 在Django项目中编写路由,就是向外暴露我们接收哪些URL的请求,除 ...

  8. 直通BAT必考题系列:JVM性能调优的6大步骤,及关键调优参数详解

    JVM内存调优 对JVM内存的系统级的调优主要的目的是减少GC的频率和Full GC的次数. 1.Full GC 会对整个堆进行整理,包括Young.Tenured和Perm.Full GC因为需要对 ...

  9. EF报错:对一个或多个实体的验证失败(Entity Framework 强制转换失败数据异常处理方法)

    1.使用MVC和EF,在保存数据的时候报错:System.Data.Entity.Validation.DbEntityValidationException: 对一个或多个实体的验证失败.有关详细信 ...

  10. nginx反向代理实现后端web的读写分离

    1.环境 角色 ip 主机名 负载均衡节点 10.0.0.11 nginx-lb01 可读写web01节点 10.0.0.12 nginx-web01 只读web02节点 10.0.0.13 ngin ...