CF1924 B
发现对于一个没有船的点 \(x_i\),代价是 \(V_l\times (r-x_i)\)。
所以对于一段没有船的区间 \([L,R]\),代价是 \(\sum\limits_L^RV_l\times (r-x_i)\)。
由于 \(V_l\) 和 \(r\) 都是定值,所以可以变为 \(V_l\times (R-L+1)\times r-V_l\times\sum\limits_L^Rx_i\)。
这个东西可以通过等差数列快速求出来,相当于我们可以快速求出来一段没有船的区间的代价。
所以我们想到用线段树来维护区间的代价。
如果要插入一艘船,设插入位置为 \(p\),插入之前最靠近 \(p\) 的船为 \(l\) 和 \(r\),我们只需要修改三段区间:
-
\([l+1,x-1]\)
-
\([x+1,r-1]\)
-
\([x,x]\),将代价改为 \(0\)。
至于找插入之前最靠近的船,可以用 set 来维护。
时间复杂度 \(O((m+q)\log n)\)。
#include<bits/stdc++.h>
typedef long long LL;
//typedef int long long;
typedef std::pair<int,int> pii;
#define ok putstrln("OrzFinderHT")
#define int long long
//#define check_time printf("%.8f\n",clocks()/CLOCK_PER_SEC)
template<typename T>
void abs(T &N){
if(N>=0) N=N;
else N=-N;
}
namespace G_{
template<typename T>
inline void read(T &a){
a=0;
int f=1;
char c=getchar();
while(c<'0'||c>'9'){
if(c=='-') f=-1;
c=getchar();
}
while(c>='0'&&c<='9') a=a*10+(int)(c-'0'),c=getchar();
a*=f;
}
inline void get_enter(){
getchar();
}
inline void get_str(std::string &str){
char c=getchar();
while(c!=' '&&c!='\n') str+=c,c=getchar();
}
template<typename T>
inline void putN(T N){
char stk[70];
short top=0;
if(N<0) putchar('-'),abs(N);
do{
stk[++top]=N%10+48;
N/=10;
}while(N);
while(top) putchar(stk[top--]);
}
template<typename T>
inline void putsp(T N){
putN(N);
putchar(' ');
}
template<typename T>
inline void putln(T N){
putN(N);
putchar('\n');
}
inline void putstr(std::string str){
int sz=str.size()-1;
for(int i=0;i<=sz;i++) putchar(str[i]);
}
inline void putstrln(std::string str){
putstr(str);
putchar('\n');
}
inline void Yes(){
putstrln("Yes");
}
inline void No(){
putstrln("No");
}
}
//using namespace get_give;
using namespace G_;
const int maxn=3e5+10;
struct tree{
LL l,r,ls,rs,lz,sum,vl,Rr;
}s[maxn*2];
int tot=0,n,m,q,X[maxn],V[maxn];
std::set<int>st;
int f(LL sx,LL wx,LL xs){
return (sx+wx)*xs/2;
}
void push_up(int p){
int ls=s[p].ls,rs=s[p].rs;
s[p].sum=s[ls].sum+s[rs].sum;
}
int build(int l,int r){
int p=++tot;
s[p].l=l,s[p].r=r;
if(l==r) return p;
int mid=(l+r)>>1;
s[p].ls=build(l,mid);
s[p].rs=build(mid+1,r);
// if(l==5&&r==8) printf("#####%lld\n",p);
// if(p==17) printf("@@@@@%lld %lld\n",s[p].l,s[p].r);
push_up(p);
return p;
}
void push_down(int p){
if(s[p].lz){
LL ls=s[p].ls,rs=s[p].rs,vl=s[p].vl,Rr=s[p].Rr;
s[ls].lz=s[rs].lz=1;
s[p].lz=0;
s[ls].sum=(s[ls].r-s[ls].l+1)*vl*Rr-vl*f(s[ls].l,s[ls].r,s[ls].r-s[ls].l+1);
s[rs].sum=(s[rs].r-s[rs].l+1)*vl*Rr-vl*f(s[rs].l,s[rs].r,s[rs].r-s[rs].l+1);
// if(p==16) ok;
s[ls].vl=s[rs].vl=vl;
s[ls].Rr=s[rs].Rr=Rr;
}
return ;
}
void update(int p,int L,int R,int vl,int Rr){
int l=s[p].l,r=s[p].r;
if(l>=L&&r<=R){
s[p].lz=1;
s[p].sum=(r-l+1)*vl*Rr-vl*f(l,r,r-l+1);
s[p].vl=vl,s[p].Rr=Rr;
return ;
}
push_down(p);
int mid=(l+r)>>1;
if(mid>=L) update(s[p].ls,L,R,vl,Rr);
if(R>mid) update(s[p].rs,L,R,vl,Rr);
push_up(p);
return ;
}
int query(int p,int L,int R){
int l=s[p].l,r=s[p].r;
if(l>=L&&r<=R) return s[p].sum;
push_down(p);
int mid=(l+r)>>1,ret=0;
if(mid>=L) ret+=query(s[p].ls,L,R);
if(R>mid) ret+=query(s[p].rs,L,R);
return ret;
}
signed main(){
// std::ios::sync_with_stdio(false);
// std::cin.tie(0);
read(n),read(m),read(q);
build(1,n);
for(int i=1;i<=m;i++) {
int loc;
read(loc);
st.insert(loc);
X[i]=loc;
}
// std::sort(X+1,X+m+1);
for(int i=1;i<=m;i++) read(V[X[i]]);
std::sort(X+1,X+m+1);
for(int i=1;i<m;i++) update(1,X[i]+1,X[i+1]-1,V[X[i]],X[i+1]);//,printf("%lld\n",query(1,2,7));
// ok;
// printf("%lld\n",query(1,3,8));
// ok;
int cnt=m;
while(q--){
int opt;
read(opt);
if(opt==1){
int x,v;
read(x),read(v);
st.insert(x);
auto it=st.lower_bound(x),l=it,r=it;
l--,r++;
int rn=*r,ln=*l;
update(1,ln+1,x-1,V[ln],x);
update(1,x+1,rn-1,v,rn);
update(1,x,x,0,0);
V[x]=v;
}else {
int l,r;
read(l),read(r);
printf("%lld\n",query(1,l,r));
}
}
return 0;
}
/*
-读入字符一定检查回车
- 能不能搜索?
-函数要有返回值!
-想好了再写!
*/
/*
1000 3 1
1 1000 318
2704361 9570636 1106813
2
*/