NKOJ传送门

describtion

给你一个序列,每个序列有编号(它本身的位置),标识符,数值。

有4种操作

op=0:l,r,x,y将编号在[l,r]的数值x+y

op=1:l,r,x,y将标识在[l,r]的数值
x+y

op=2:l,r将编号在[l,r]的数值和

op=3:l,r将标识在[l,r]的数值和

solution

kd-tree魔板……

维护两维

修改和线段树一样打标记即可。

还是写了很久

code

点击查看代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+5;
const int mod=536870912;
int idx,op,n,m;
ll M,A;
struct data {
int z[2];
bool operator<(const data &u) const{return z[idx]<u.z[idx];}
}a[N];
struct node {int mid,mn[2],mx[2],sz;ll val,add=0,mul=1,sum=0;}T[N];
struct kd_tree {
int nd,ls[N],rs[N];
void Build(int x,int l,int r) {
idx^=1;int idt(idx);
int mid=(l+r)>>1;
T[x].mid=mid;T[x].sz=1;
nth_element(a+l,a+mid,a+r+1);
T[x].mn[0]=T[x].mx[0]=a[mid].z[0];T[x].mn[1]=T[x].mx[1]=a[mid].z[1];
if(l!=mid) {
ls[x]=++nd;int L(ls[x]);
Build(nd,l,mid-1),idx=idt;
T[x].mn[0]=min(T[x].mn[0],T[L].mn[0]),T[x].mn[1]=min(T[x].mn[1],T[L].mn[1]);
T[x].mx[0]=max(T[x].mx[0],T[L].mx[0]),T[x].mx[1]=max(T[x].mx[1],T[L].mx[1]);
T[x].sz+=T[L].sz;
}
if(r!=mid) {
rs[x]=++nd;int R(rs[x]);
Build(nd,mid+1,r);
T[x].mn[0]=min(T[x].mn[0],T[R].mn[0]),T[x].mn[1]=min(T[x].mn[1],T[R].mn[1]);
T[x].mx[0]=max(T[x].mx[0],T[R].mx[0]),T[x].mx[1]=max(T[x].mx[1],T[R].mx[1]);
T[x].sz+=T[R].sz;
}
// printf("%d pos=(%d,%d) z0:[%d,%d] z1:[%d,%d]\n",x,a[mid].z[0],a[mid].z[1],T[x].mn[0],T[x].mx[0],T[x].mn[1],T[x].mx[1]);
}
void mk_tree() {
++nd;idx=0;
Build(1,1,n);
}
inline void Up_mul(int x,ll w) {
T[x].mul=T[x].mul*w%mod;T[x].add=T[x].add*w%mod;
T[x].val=T[x].val*w%mod;T[x].sum=T[x].sum*w%mod;
}
inline void Up_add(int x,ll w) {
T[x].add=(T[x].add+w)%mod;
T[x].sum=(T[x].sum+T[x].sz*w)%mod;T[x].val=(T[x].val+w)%mod;
}
void P_dw(int x) {
if(T[x].mul!=1) {
if(ls[x])Up_mul(ls[x],T[x].mul);
if(rs[x])Up_mul(rs[x],T[x].mul);
T[x].mul=1;
}
if(T[x].add) {
if(ls[x])Up_add(ls[x],T[x].add);
if(rs[x])Up_add(rs[x],T[x].add);
T[x].add=0;
}
}
void P_up(int x) {T[x].sum=(T[ls[x]].sum+T[rs[x]].sum+T[x].val)%mod;}
void Update(int x,int l,int r) {
if(T[x].mx[op]<l||T[x].mn[op]>r) return;
if(T[x].mn[op]>=l&&T[x].mx[op]<=r) {Up_mul(x,M),Up_add(x,A);return;}
P_dw(x);
int pz(a[T[x].mid].z[op]);
if(pz>=l&&pz<=r) {T[x].val=(T[x].val*M+A)%mod;}
if(ls[x]) Update(ls[x],l,r);
if(rs[x]) Update(rs[x],l,r);
P_up(x);
}
ll Ask(int x,int l,int r) {
if(T[x].mx[op]<l||T[x].mn[op]>r) return 0;
if(l<=T[x].mn[op]&&T[x].mx[op]<=r) {return T[x].sum;}
P_dw(x);
ll res(0);int pz(a[T[x].mid].z[op]);
if(pz>=l&&pz<=r) {res=T[x].val;}
if(ls[x]) res=(res+Ask(ls[x],l,r))%mod;
if(rs[x]) res=(res+Ask(rs[x],l,r))%mod;
return res;
}
}KD;
int main() {
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) {a[i].z[0]=i;scanf("%d",&a[i].z[1]);}
KD.mk_tree();
for(int i=1;i<=m;i++) {
int opt,l,r;
scanf("%d%d%d",&opt,&l,&r);
if(!opt) {op=0;scanf("%lld%lld",&M,&A);KD.Update(1,l,r);}
else if(opt==1) {op=1;scanf("%lld%lld",&M,&A);KD.Update(1,l,r);}
else if(opt==2) {op=0;printf("%lld\n",KD.Ask(1,l,r));}
else if(opt==3) {op=1;printf("%lld\n",KD.Ask(1,l,r));}
}
return 0;
}

最新文章

  1. Trilateration三边测量定位算法
  2. Java中时间日期格式化
  3. 使用SharpSSH连接服务器报Algorithm negotiation fail解决办法
  4. Linux Shell系列教程之(十六) Shell输入输出重定向
  5. cocos基础教程(5)数据结构介绍之cocos2d::Map&lt;K,V&gt;
  6. FreeMarker中List排序
  7. 【好文翻译】一步一步教你使用Spire.Doc转换Word文档格式
  8. gentoo装X服务器时显卡选择
  9. 同台电脑部署多组Tomcat负载均衡(或集群)
  10. .NET平台和开发.
  11. 可视化利器Visdom
  12. 蓝牙SDP协议概述
  13. 一台PC双网卡,一个外网一个内网
  14. 10.11 rbac权限
  15. DNA拷贝数变异CNV检测——基础概念篇
  16. angularjs 常用方法
  17. J - Clairewd’s message HDU - 4300(扩展kmp)
  18. IO多路复用之epoll(一)讲解
  19. [bzoj1016][JSOI2008]最小生成树计数 (Kruskal + Matrix Tree 定理)
  20. java中成员变量、代码块、构造函数运行顺序

热门文章

  1. JdGrid排序问题
  2. 在keil中加入DSP库并且使用arm_math.h
  3. Django + Taro 前后端分离项目实现企业微信登录
  4. .Net Core 进程守护之Supervisor使用
  5. 如何使用Android可视化埋点
  6. Leetcode216/39/40/77之回溯解决经典组合问题
  7. Java之万年历
  8. Markdown练习
  9. 新手入门C语言第八章:C循环
  10. nodejs的tream(流)解析与模拟文件读写流源码实现