Codeforces

思路

定义\(f_{l,r}(x)\)表示数\(x\)从\(l\)进去\(r\)出来的时候会变成什么样子。容易发现这个函数是个分段函数,每一段都是斜率为1的一次函数,并且段数就是区间长度。(可能有什么+1-1的)

如果我们能在线段树维护出这个东西,那么查询的时候在线段树上拉出一些函数,依次代进去,就可以了。

两个函数怎么复合呢?做一个two pointers,可以证明这样复杂度是线性的。

咋证明?懒得说了,去别的神仙的博客看吧。

代码

实现的时候似乎不能把\(l,r\)都存下来,否则询问会特别慢。

为什么呢?我也不知道……

#include<bits/stdc++.h>
clock_t t=clock();
namespace my_std{
using namespace std;
#define pii pair<int,int>
#define fir first
#define sec second
#define MP make_pair
#define rep(i,x,y) for (int i=(x);i<=(y);i++)
#define drep(i,x,y) for (int i=(x);i>=(y);i--)
#define go(x) for (int i=head[x];i;i=edge[i].nxt)
#define templ template<typename T>
#define sz 1110002
typedef long long ll;
typedef double db;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
templ inline T rnd(T l,T r) {return uniform_int_distribution<T>(l,r)(rng);}
templ inline bool chkmax(T &x,T y){return x<y?x=y,1:0;}
templ inline bool chkmin(T &x,T y){return x>y?x=y,1:0;}
templ inline void read(T& t)
{
t=0;char f=0,ch=getchar();double d=0.1;
while(ch>'9'||ch<'0') f|=(ch=='-'),ch=getchar();
while(ch<='9'&&ch>='0') t=t*10+ch-48,ch=getchar();
if(ch=='.'){ch=getchar();while(ch<='9'&&ch>='0') t+=d*(ch^48),d*=0.1,ch=getchar();}
t=(f?-t:t);
}
template<typename T,typename... Args>inline void read(T& t,Args&... args){read(t); read(args...);}
char __sr[1<<21],__z[20];int __C=-1,__zz=0;
inline void Ot(){fwrite(__sr,1,__C+1,stdout),__C=-1;}
inline void print(register int x)
{
if(__C>1<<20)Ot();if(x<0)__sr[++__C]='-',x=-x;
while(__z[++__zz]=x%10+48,x/=10);
while(__sr[++__C]=__z[__zz],--__zz);__sr[++__C]='\n';
}
void file()
{
#ifdef NTFOrz
freopen("a.in","r",stdin);
#endif
}
inline void chktime()
{
#ifndef ONLINE_JUDGE
cout<<(clock()-t)/1000.0<<'\n';
#endif
}
#ifdef mod
ll ksm(ll x,int y){ll ret=1;for (;y;y>>=1,x=x*x%mod) if (y&1) ret=ret*x%mod;return ret;}
ll inv(ll x){return ksm(x,mod-2);}
#else
ll ksm(ll x,int y){ll ret=1;for (;y;y>>=1,x=x*x) if (y&1) ret=ret*x;return ret;}
#endif
// inline ll mul(ll a,ll b){ll d=(ll)(a*(double)b/mod+0.5);ll ret=a*b-d*mod;if (ret<0) ret+=mod;return ret;}
}
using namespace my_std; int n;ll P;
ll a[sz]; struct hh{ll l,b;}; // x \in [l,r], y=x+b typedef vector<hh> func;
func tr[sz<<1];
#define ls k<<1
#define rs k<<1|1
#define lson ls,l,mid
#define rson rs,mid+1,r
ll calc(const func &V,ll x)
{
int l=0,r=(int)V.size()-1,pos=0;
while (l<=r)
{
int mid=(l+r)>>1;
if (x>=V[mid].l) pos=mid,l=mid+1;
else r=mid-1;
}
return x+V[pos].b;
}
func merge(func A,const func &B)
{
int p=0;
func ret;
int aa=A.size(),bb=B.size();
#define add(L,BB) ((ret.empty()||ret.back().b!=BB)?ret.push_back((hh){L,BB}),0:0)
for (int i=0;i<=(int)A.size()-1;)
{
ll yl=A[i].l+A[i].b,yr;
if (A[i].l==-1e17) yl=-1e17;
if (i==aa-1) yr=1e17; else yr=A[i+1].l-1+A[i].b;
while (p&&B[p].l>yl) --p;
while (p<bb-1&&B[p+1].l-1<yl) ++p;
ll r;
if (p==bb-1) r=1e17; else r=B[p+1].l-1;
if (r<yr) add(A[i].l,A[i].b+B[p].b),A[i].l=r-A[i].b+1;
else add(A[i].l,A[i].b+B[p].b),++i;
}
return ret;
#undef add
}
void build(int k,int l,int r)
{
if (l==r) { tr[k].push_back((hh){-(ll)1e17,a[l]}),tr[k].push_back((hh){P-a[l],a[l]-P}); return; }
int mid=(l+r)>>1;
build(lson),build(rson);
tr[k]=merge(tr[ls],tr[rs]);
}
ll query(int k,int l,int r,int x,int y,ll w)
{
if (x<=l&&r<=y) return calc(tr[k],w);
int mid=(l+r)>>1;
if (x<=mid) w=query(lson,x,y,w);
if (y>mid) w=query(rson,x,y,w);
return w;
} int main()
{
file();
int Q;
read(n,Q,P);
rep(i,1,n) read(a[i]);
build(1,1,n);
int l,r;
while (Q--) read(l,r),printf("%I64d\n",(long long)query(1,1,n,l,r,0));
return 0;
}

Codeforces 1172F Nauuo and Bug [线段树]的更多相关文章

  1. 【杂题】[CodeForces 1172F] Nauuo and Bug【数据结构】【线段树】

    Description 给出一个长度为n的序列a和一个整数p 有m组询问,每组询问给出一个区间\([l,r]\) 你需要给出下面这个过程的结果 ans = 0 for i from l to r { ...

  2. codeforces Good bye 2016 E 线段树维护dp区间合并

    codeforces Good bye 2016 E 线段树维护dp区间合并 题目大意:给你一个字符串,范围为‘0’~'9',定义一个ugly的串,即串中的子串不能有2016,但是一定要有2017,问 ...

  3. codeforces 22E XOR on Segment 线段树

    题目链接: http://codeforces.com/problemset/problem/242/E E. XOR on Segment time limit per test 4 seconds ...

  4. Codeforces 588E. A Simple Task (线段树+计数排序思想)

    题目链接:http://codeforces.com/contest/558/problem/E 题意:有一串字符串,有两个操作:1操作是将l到r的字符串升序排序,0操作是降序排序. 题解:建立26棵 ...

  5. Codeforces Gym 100803G Flipping Parentheses 线段树+二分

    Flipping Parentheses 题目连接: http://codeforces.com/gym/100803/attachments Description A string consist ...

  6. Codeforces GYM 100114 D. Selection 线段树维护DP

    D. Selection Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100114 Descriptio ...

  7. Codeforces 444C DZY Loves Colors(线段树)

    题目大意:Codeforces 444C DZY Loves Colors 题目大意:两种操作,1是改动区间上l到r上面德值为x,2是询问l到r区间总的改动值. 解题思路:线段树模板题. #inclu ...

  8. Codeforces 85D Sum of Medians(线段树)

    题目链接:Codeforces 85D - Sum of Medians 题目大意:N个操作,add x:向集合中加入x:del x:删除集合中的x:sum:将集合排序后,将集合中全部下标i % 5 ...

  9. [Codeforces]817F. MEX Queries 离散化+线段树维护

    [Codeforces]817F. MEX Queries You are given a set of integer numbers, initially it is empty. You sho ...

随机推荐

  1. 图解javascript的this指向

    图解javascript的this指向 作者: HerryLo 本文永久有效链接: https://github.com/AttemptWeb...... 以下就只有两张图,请放心食用!! #简版th ...

  2. iframe 边框(界面技术)

    一.iframe 的边框很难看,想去掉,使用CSS的border:none在IE(8)上没有,只能用iframe 自带属性frameBorder="0"来设置. 二.iframe与 ...

  3. 【转载】C#中string类使用Substring方法截取字符串

    在C#的字符串操作过程中,截取字符串是一种常见的字符串操作,可使用string类的Substring方法来完成字符串的截取操作,该方法支持设定截取的开始位置以及截取的字符串长度等参数,Substrin ...

  4. JavaScript 自己写一个 replaceAll() 函数

    JavaScript 的  replace()  方法可以在字符串中用一些字符替换另一些字符,或替换一个与正则表达式匹配的子串. 但是,只输入字符串的话,仅替换第一个字符,当然也可以用正则表达式来进行 ...

  5. 敏感词检测、屏蔽设计(iOS & Android)

    敏感词检测 服务器端最常使用的算法是DFA算法.如果服务器端使用java实现常规的DFA算法,假若... 源码:https://github.com/qiyer/DFA_Cplusplus

  6. canvas教程(三) 绘制曲线

    经过 canvas 教程(二) 绘制直线 我们知道了 canvas 的直线是怎么绘制的 而本次是给大家带来曲线相关的绘制 绘制圆形 在 canvas 中我们可以使用 arc 方法画一个圆 contex ...

  7. Struts框架笔记04_拦截器_标签库

    目录 1. Struts2的拦截器 1.1 拦截器概述 1.2 拦截器的实现原理 1.3 Struts的执行流程 1.4 拦截器入门 1.4.1 环境搭建 1.4.2 编写拦截器 1.4.3 配置拦截 ...

  8. 【转】国内CPU现状

    首页 博客 学院 下载 图文课 论坛 APP CSDN                            CSDN学院                            问答 商城 VIP会员 ...

  9. java容器tomat,jboss支持内部读取软链接

    tomcat,jboss允许软链接 作用:当war包解压过后,需要将内部进行链接到外部的可移动存储上时,就需要使用此功能. tomcat默认是不开启tomcat链接的,需要手动添加配置项. 在tomc ...

  10. docker发展历程

    docker发展历程 docker本身不是容器,它只是一个更加易用的前端管理器. 最早期的容器技术概念是用chroot来实现隔离,但是chroot只是提供了对进程文件目录虚拟化的功能,不能防止进程恶意 ...