Comet OJ - Contest #14 (D,E,F)

D - 转转的数据结构题

题意

有一个长度为 m m m的整数序列。初始所有元素都是 0 0 0

有一个长度为 n n n的操作序列,每个操作形如 ( l , r , v ) (l,r,v) (l,r,v),表示将序列中的下标在 [ l , r ] [l,r] [l,r]的元素的值赋为 v v v

q q q次询问,每次给出 x , y x,y x,y,表示只进行编号在 [ x , y ] [x,y] [x,y]的操作所得到的序列的所有元素的和。询问之间是独立的。

n , m , q ≤ 5 × 1 0 5 , v ≤ 1 0 9 n,m,q\le 5\times 10^5, v\le 10^9 n,m,q5×105,v109

Sol

如果依次进行所有的操作,每一次操作的时候覆盖掉的区间中,极长的由相同元素构成的区间的数量的和是 O ( n ) O(n) O(n)的。

考虑进行完前 y y y个操作时得到的序列,我们只需要知道这个序列中在第 x x x次操作以前就已经被赋值的元素的和,用现在的序列中元素的和减去它们就可以得到询问 x , y x,y x,y的答案。

依次进行所有操作,在维护所有极长的由相同元素构成的段的同时,维护插入时间小于等于每个 x x x的所有元素的和即可。

Code

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <set>
#include <vector>
#define PB push_back
#define PII pair<int,int>
#define MP make_pair
#define fir first
#define sec second
#define ll long long
using namespace std;
template <class T>
inline void rd(T &x) {
   
	x=0; char c=getchar(); int f=1;
	while(!isdigit(c)) {
    if(c=='-') f=-1; c=getchar(); }
	while(isdigit(c)) x=x*10-'0'+c,c=getchar(); x*=f;
}
const int N=5e5+10;
int n;

ll c[N];
void add(int i,ll t) {
    for(;i;i-=i&-i) c[i]+=t; }
ll query(int i) {
    ll ans=0; for(;i<=n;i+=i&-i) ans+=c[i]; return ans; }

struct seg {
   
	int ty,p,t,v;
	seg(int ty=0,int p=0,int t=0,int v=0): ty(ty),p(p),t(t),v(v) {
   }
	friend bool operator <(seg A,seg B) {
   
		return A.p==B.p?A.ty>B.ty:A.p<B.p;
	}
};
set<seg> s;

struct Que {
   
	int l,r,v;
}Q[N];
vector<PII> U[N];
int m,q;

ll ans[N];

void del(seg A) {
   
	add(A.t,-A.v*A.ty*(ll)A.p);
	s.erase(A);
}
void add(seg A) {
   
	add(A.t,A.v*A.ty*(ll)A.p);
	s.insert(A);
}

vector<seg> D;

int main() {
   
	rd(n),rd(m),rd(q);
	for(int i=1;i<=n;++i) rd(Q[i].l),rd(Q[i].r),rd(Q[i].v);
	for(int i=1,l,r;i<=q;++i) {
   
		rd(l),rd(r);
		U[r].PB(MP(l,i));
	}
	s.insert(seg(-1,1,0,0));
	s.insert(seg(1,m+1,0,0));
	for
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值