K-xay loves sequence

首先不考虑模kkk的限制,容易想到对原数组做一个差分得到di=ai−ai−1d_i=a_i-a_{i-1}di​=ai​−ai−1​,显然对于∀1≤i≤nai=0\forall_{1\leq i\leq n} a_i=0∀1≤i≤n​ai​=0 等价于∀1≤i≤ndi=0\forall_{1\leq i\leq n} d_i=0∀1≤i≤n​di​=0,而对于原数组的区间±1\pm1±1等价于在差分数组ddd中找到两个数一个数+1另一个数-1,或者说找到一个位置pos\text {pos}pos单独+1或者-1(这意味着原数组[apos→an]±1[a_{\text{pos}}\to a_n] \pm1[apos​→an​]±1)。上面的最优解显然是max⁡{∑d+,∣∑d−∣}\max\{\sum d_+,|\sum{d_-}|\}max{∑d+​,∣∑d−​∣}

上述变换有些麻烦,如果我们引入an+1=0a_{n+1}=0an+1​=0,并且引入dn+1=an+1−and_{n+1}=a_{n+1}-a_ndn+1​=an+1​−an​后,对于原数组进行区间±1\pm1±1等价于在差分数组d1→n+1d_{1\to n+1}d1→n+1​选两个数一个+1另一个-1。并且不难发现无论怎么进行上述操作总有∑i=1n+1di=0\sum_{i=1}^{n+1} d_i=0∑i=1n+1​di​=0最优解max⁡{∑d+,∣∑d−∣}=∑i=1n+1∣di∣2\max\{\sum d_+,|\sum{d_-}|\}=\frac{\sum_{i=1}^{n+1} |d_i|}{2}max{∑d+​,∣∑d−​∣}=2∑i=1n+1​∣di​∣​


hipamp题解

考虑模kkk的意义下意味着我们可以花费0的代价使得某些ai±ka_i\pm kai​±k,对应在差分数组上即是di±k,di+1∓kd_i\pm k,d_{i+1}\mp kdi​±k,di+1​∓k,换句话说现在可以让成对的di±k,dj∓kd_i\pm k,d_j\mp kdi​±k,dj​∓k最终结果仍然是让∀1≤i≤ndi+1=0\forall_{1\leq i\leq n} d_{i+1}=0∀1≤i≤n​di+1​=0。

不难发现di=di+kd_i=d_i+kdi​=di​+k那么一定有di<0d_i<0di​<0,同理di=di−kd_i=d_i-kdi​=di​−k那么一定有di≥0d_i\ge0di​≥0

如果di=di+kd_i=d_i+kdi​=di​+k,那么贡献从∣di∣2→∣di+k∣2,Δ=k−2∣di∣2\frac{|d_i|}{2}\to\frac{|d_i+k|}{2},\Delta=\frac{k-2|d_i|}{2}2∣di​∣​→2∣di​+k∣​,Δ=2k−2∣di​∣​

如果di=di−kd_i=d_i-kdi​=di​−k,那么贡献从∣di∣2→∣di−k∣2,Δ=k−2∣di∣2\frac{|d_i|}{2}\to\frac{|d_i-k|}{2},\Delta=\frac{k-2|d_i|}{2}2∣di​∣​→2∣di​−k∣​,Δ=2k−2∣di​∣​

于是只需要把did_idi​分为小于0的一组和大于0的一组,按照Δ=k−2∣di∣2\Delta=\frac{k-2|d_i|}{2}Δ=2k−2∣di​∣​从小到大排序,每次取两数组中开头的两个(Δ+)+(Δ−)(\Delta_+)+(\Delta_-)(Δ+​)+(Δ−​),如果能使答案变小即(Δ+)+(Δ−)<0(\Delta_+)+(\Delta_-)<0(Δ+​)+(Δ−​)<0即一直取。


首先如果没有区间l,rl,rl,r的限制,每次询问只给一个kkk的话可以二分取了多少对d−+k,d+−kd_{-}+k,d_{+}-kd−​+k,d+​−k,快速的求出答案。显然加上区间限制只需要套一个主席树即可。

注意对于[l,r][l,r][l,r]区间来说差分数组是(al−0),dl+1,…dr,(0−ar)(a_l-0),d_{l+1},\dots d_{r},(0-a_r)(al​−0),dl+1​,…dr​,(0−ar​),也就是主席树维护did_idi​,然后每次询问会增添两个数(al−0)(a_l-0)(al​−0)和(0−ar)(0-a_r)(0−ar​),一个插在正主席树,一个在负主席树。一个显然的想法是单点修改2次,然后询问过后删除,就如下面注释的代码。但是主席树不支持修改,因为修改不仅仅影响一棵主席树,而是会影响许多棵树,于是只需要在询问的时候带上这个数即可。

#include<bits/stdc++.h>
using namespace std;
using ll=long long;
template <class T=int> T rd()
{T res=0;T fg=1;char ch=getchar();while(!isdigit(ch)) {if(ch=='-') fg=-1;ch=getchar();}while( isdigit(ch)) res=(res<<1)+(res<<3)+(ch^48),ch=getchar();return res*fg;
}
const int N=200010;
const int U=(1ll<<31)-1;
int a[N],d[N];
ll s[N];
int n,m;
struct node
{int l,r;ll v,ct;
}tree[N*100];
int rt[2][N],cnt;
void update(int l,int r,int pre,int &u,int v,int c)
{u=++cnt;tree[u]=tree[pre];tree[u].ct+=c;tree[u].v+=v*c;if(l==r) return;int mid=l+r>>1;if(v<=mid) update(l,mid,tree[pre].l,tree[u].l,v,c);elseupdate(mid+1,r,tree[pre].r,tree[u].r,v,c);
}
// void change(int &u,int l,int r,int v,int c)
// {//     if(!u) u=++cnt;
//     tree[u].ct+=c;
//     tree[u].v+=v*c;
//     if(l==r) return;
//     int mid=l+r>>1;
//     if(v<=mid)
//         change(tree[u].l,l,mid,v,c);
//     else
//         change(tree[u].r,mid+1,r,v,c);
// }
// // 求前k大的sum
// ll query(int l,int r,int L,int R,int k)
// {//     if(!k) return 0ll;
//     if(l==r) return 1ll*k*l;
//     int mid=l+r>>1;
//     int tmp=tree[tree[R].r].ct-tree[tree[L].r].ct;
//     if(k<=tmp)
//         return query(mid+1,r,tree[L].r,tree[R].r,k);
//     else
//         return (1ll*tree[tree[R].r].v-tree[tree[L].r].v)+query(l,mid,tree[L].l,tree[R].l,k-tmp);
// }
// // 计算数组l~r的答案 取前k大
// ll calc(int l,int r,int k,int x)
// {//     // a[l]+d[l+1]~d[r]+abs(0-a[r])//     ll v=(s[r]-s[l]+a[r]+a[l])/2;
//     ll s1=query(0,U,rt[0][l],rt[0][r],k);
//     ll s2=query(0,U,rt[1][l],rt[1][r],k);
//     return v-s1-s2+1ll*k*x;
// }
// 求前k大的sum
ll query(int l,int r,int L,int R,int k,int v)
{if(!k) return 0ll;if(l==r) return 1ll*k*l;int mid=l+r>>1;int tmp=tree[tree[R].r].ct-tree[tree[L].r].ct+(mid<v&&v<=r);if(k<=tmp)  return query(mid+1,r,tree[L].r,tree[R].r,k,v);else return (1ll*tree[tree[R].r].v-tree[tree[L].r].v)+(mid<v&&v<=r)*v+query(l,mid,tree[L].l,tree[R].l,k-tmp,v);
}
// 计算数组l~r的答案 取前k大
ll calc(int l,int r,int k,int x)
{// a[l]+d[l+1]~d[r]+abs(0-a[r])ll v=(s[r]-s[l]+a[r]+a[l])/2;ll s1=query(0,U,rt[0][l],rt[0][r],k,a[l]);ll s2=query(0,U,rt[1][l],rt[1][r],k,a[r]);return v-s1-s2+1ll*k*x;
}
int main()
{n=rd(),m=rd();for(int i=1;i<=n;i++) {a[i]=rd();d[i]=abs(a[i]-a[i-1]);s[i]=s[i-1]+d[i];if(a[i]>=a[i-1]) {update(0,U,rt[0][i-1],rt[0][i],d[i],1);rt[1][i]=rt[1][i-1];}else{update(0,U,rt[1][i-1],rt[1][i],d[i],1);rt[0][i]=rt[0][i-1];}}while(m--){int x=rd(),y=rd(),k=rd();// a[x] d[x+1] d[x+2]... d[y] abs(0-a[y])// change(rt[0][y],0,U,a[x],+1);// change(rt[1][y],0,U,a[y],+1);int l=0,r=min(tree[rt[0][y]].ct-tree[rt[0][x]].ct,tree[rt[1][y]].ct-tree[rt[1][x]].ct)+1;//cout<<l<<' '<<r<<'\n';while(l<r){int mid=l+r>>1;if(calc(x,y,mid,k)<=calc(x,y,mid+1,k)) r=mid;else l=mid+1;}printf("%lld\n",calc(x,y,l,k));// change(rt[0][y],0,U,a[x],-1);// change(rt[1][y],0,U,a[y],-1);}return 0;
}

2021牛客暑期多校训练营7 K-xay loves sequence(主席树+二分)相关推荐

  1. 【2021牛客暑期多校训练营7】xay loves trees(dfs序,维护根出发的链)

    F xay loves trees 题意: 给出两棵树,由这两棵树根据规则可以生成一个图,规则如下:如果u , v在第一棵树中满足其中一个点是另一个点祖先且最终所有所选的点都互相联通,在第二棵树中满足 ...

  2. 【2021牛客暑期多校训练营7 】 xay loves count

    题目:点这里 要求:给出一组数,求满足 的i,j,k有多少个 分析:列举ak,对每一个找出满足题意的i,j然后计算有多少个(三个数可以相同,找i,j的范围是0~sqrt(ak): 下面还是队友代码时间 ...

  3. 2021牛客暑期多校训练营2 K Stack

    题目大意: 题目告诉你利用单调栈几个点前面比它小并包含它自身的元素有多少个 让你构造一个包含1到n并每个数字只出现一次的序列 思路: 我们可以对于每个点都算出栈中元素的数量 对于没有给出的点的栈中元素 ...

  4. 2021牛客暑期多校训练营9

    2021牛客暑期多校训练营9 题号 题目 知识点 A A Math Challenge B Best Subgraph C Cells D Divide-and-conquer on Tree E E ...

  5. 2021牛客暑期多校训练营5

    2021牛客暑期多校训练营5 题号 题目 知识点 A Away from College B Boxes 概率 C Cheating and Stealing D Double Strings 线性d ...

  6. 2021牛客暑期多校训练营4

    2021牛客暑期多校训练营4 题号 题目 知识点 A Course B Sample Game C LCS D Rebuild Tree E Tree Xor 思维+线段树 F Just a joke ...

  7. 2021牛客暑期多校训练营3

    2021牛客暑期多校训练营3 题号 题目 知识点 A Guess and lies B Black and white C Minimum grid 二分图匹配 D Count E Math 数论+打 ...

  8. 2021牛客暑期多校训练营2

    2021牛客暑期多校训练营2 题号 题目 知识点 A Arithmetic Progression B Cannon C Draw Grids D Er Ba Game E Gas Station F ...

  9. 2021牛客暑期多校训练营1

    2021牛客暑期多校训练营1 题号 题目 知识点 难度 A Alice and Bob 博弈论 B Ball Dropping 计算几何 签到 C Cut the Tree D Determine t ...

  10. 2021牛客暑期多校训练营2,签到题CDFKI

    2021牛客暑期多校训练营2 题号 标题 已通过代码 通过率 团队的状态 A Arithmetic Progression 点击查看 6/72 未通过 B Cannon 点击查看 34/104 未通过 ...

最新文章

  1. 越阳刚的男人越容易生女孩
  2. 6.QT信号槽的时序分析
  3. 《算法与数据结构专场》BitMap算法介绍
  4. python使用rabbitmq阻塞_python – Celery/RabbitMQ unacked消息阻塞队列?
  5. 机器学习火热,SQL 开发人员有何用?
  6. 单用户模式 启动 mysql_单用户模式连接以及故障排除
  7. Fang Fang 思维题
  8. ntp子母钟(gps子母钟系统)时钟系统在智能交通系统中的重要性
  9. 2021最新Java面试真题解析!java开发技能掌握
  10. 量子计算(十五):半导体量子芯片
  11. Sails.js简介
  12. 华为云PB级数据库GaussDB(for Redis)揭秘第八期:用高斯 Redis 进行计数
  13. vue组件可视化_Vue HTML5音频可视化组件
  14. 关于STM32F407ZGT6的一些知识小结及串口1程序
  15. 高德h5地图api接口_H5,JS中使用微信、高德获取定位
  16. 沈询 java进阶,7细品这杯香浓的咖啡 阿里中间件高级专家沈询的JAVA之旅
  17. 通信系统与网络思维导图
  18. 【IT公司笔试面试】75道逻辑推理题及答案
  19. FAT16和FAT32目录结构分析
  20. 【转】揭秘迅雷VIP用户的破解方法

热门文章

  1. pixelbook安装linux系统,谷歌Pixelbook可以运行Fuchsia操作系统 正测试
  2. linux自动应答,08. 创建 ks.cfg自动应答文件
  3. 算法题目——质量(POJ-1862)
  4. mysql无法创建新用户_如何mysql禁止创建新用户
  5. 7-8 最优服务次序问题 (10 分)
  6. 7-1 活动选择问题 (25 分)(思路+详解+扩展)宝 今天你AC了吗!!!
  7. C++未定义行为-数组越界
  8. random(随机函数生成)
  9. A Mini Locomotive POJ - 1976(动态规划+思维)
  10. 数据结构与索引-- B+树索引