Codeforces 1172F Nauuo and Bug [线段树]
思路
定义\(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 [线段树]的更多相关文章
- 【杂题】[CodeForces 1172F] Nauuo and Bug【数据结构】【线段树】
Description 给出一个长度为n的序列a和一个整数p 有m组询问,每组询问给出一个区间\([l,r]\) 你需要给出下面这个过程的结果 ans = 0 for i from l to r { ...
- codeforces Good bye 2016 E 线段树维护dp区间合并
codeforces Good bye 2016 E 线段树维护dp区间合并 题目大意:给你一个字符串,范围为‘0’~'9',定义一个ugly的串,即串中的子串不能有2016,但是一定要有2017,问 ...
- codeforces 22E XOR on Segment 线段树
题目链接: http://codeforces.com/problemset/problem/242/E E. XOR on Segment time limit per test 4 seconds ...
- Codeforces 588E. A Simple Task (线段树+计数排序思想)
题目链接:http://codeforces.com/contest/558/problem/E 题意:有一串字符串,有两个操作:1操作是将l到r的字符串升序排序,0操作是降序排序. 题解:建立26棵 ...
- Codeforces Gym 100803G Flipping Parentheses 线段树+二分
Flipping Parentheses 题目连接: http://codeforces.com/gym/100803/attachments Description A string consist ...
- Codeforces GYM 100114 D. Selection 线段树维护DP
D. Selection Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100114 Descriptio ...
- Codeforces 444C DZY Loves Colors(线段树)
题目大意:Codeforces 444C DZY Loves Colors 题目大意:两种操作,1是改动区间上l到r上面德值为x,2是询问l到r区间总的改动值. 解题思路:线段树模板题. #inclu ...
- Codeforces 85D Sum of Medians(线段树)
题目链接:Codeforces 85D - Sum of Medians 题目大意:N个操作,add x:向集合中加入x:del x:删除集合中的x:sum:将集合排序后,将集合中全部下标i % 5 ...
- [Codeforces]817F. MEX Queries 离散化+线段树维护
[Codeforces]817F. MEX Queries You are given a set of integer numbers, initially it is empty. You sho ...
随机推荐
- 物流管理系统(SSM+vue+shiro)【前后台】
一.简单介绍项目 该项目是属于毕业设计项目之一,有前台的用户下单.有司机进行接单.有管理员进行操作后台,直接进入主题 毕设.定制开发 联系QQ:761273133 登录主页: 手机号码+验证码登录 或 ...
- Docker安装带中文全文搜索插件zhparser的Postgresql数据库
上一篇讲了在已经安装了PG数据库的情况下,安装全文搜索插件zhparser遇到的问题.在一个全新的环境中安装带有全文搜索插件zhparser的PG数据库,可以使用已经做好的Docker镜像,在安装的过 ...
- IdentityServer4实现Oauth2.0四种模式之隐藏模式
接上一篇:IdentityServer4实现OAuth2.0四种模式之密码模式,密码模式将用户的密码暴露给了客户端,这无疑是不安全的,隐藏模式可以解决这个问题,由用户自己在IdentityServ ...
- ssh免秘钥
用过好几次免秘钥,但是每次都会忘了应该把copy谁的公钥到另外用户的.ssh文件夹 这里专门记录一次 注意点: A要使用ssh免密登录到B用户下(可以使远程服务器),就把A的用户下的.ssh文件的id ...
- linux ubuntu-16.04-配置java1.8和Tomcat8
前言 第一次使用linux ubuntu16.04 服务器,所以做一下常用配置的记录. JDK 1.创建存放jdk的目录 一般在usr/local下创建一个java文件夹 cd /usr/local ...
- kubernetes第九章--管理机密信息
- Part_three:Redis持久化存储
redis持久化存储 Redis是一种内存型数据库,一旦服务器进程退出,数据库的数据就会丢失,为了解决这个问题,Redis提供了两种持久化的方案,将内存中的数据保存到磁盘中,避免数据的丢失. 1.RD ...
- redux的理解
Redux 这里介绍下我对Redux的理解,不涉及如何使用Redux. Redux 官网介绍: A predictable state container for JavaScript apps.(一 ...
- 安装License需要重启
"only commands for license handling are allowed in current state" Can you confirm if licen ...
- Vue中v-model解析、sync修饰符解析
上善若水,水善利萬物而不爭.——<道德經> 简介 在平时开发是经常用到一些父子组件通信,经常用到props.vuex等等,这里面记录另外的三种方式v-model.sync是怎么使用,再说是 ...