小C的棋王之路------(ODT)
小C的棋王之路
https://ac.nowcoder.com/acm/contest/5759/D
相信珂学emmm,一眼板子题,直接珂朵莉树,set针对区间覆值进行启发式合并,使用内置二分函数lower_bound分裂区间左右端点,然后暴力模拟,十分简单粗暴,操作1和操作2都是暴力,直接for,为何不会超时,就因为有操作3,每次区间赋值,我们可以将区间合并为一个,直接用结构体表示struce node={l,r,val},这就是珂朵莉树的精髓了,至于操作4的添加节点,因为一般来说set里面都会插入一个末尾节点,下标比数组大1,为了方便分裂区间右端点为数组末尾的操作,所以用一个变量记录数组末尾下标,然后每次操作4,先删除set的末尾节点,然后扩展一个新节点,然后标记末尾变量+1,再插入末尾标记。
至于结构体内为何要用一个mutable,因为不加就不行= =,加就对了
#include <cctype>
#include <cfloat>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <algorithm>
#include <deque>
#include <fstream>
#include <functional>
#include <iomanip>
#include <iostream>
#include <istream>
#include <iterator>
#include <list>
#include <map>
#include <ostream>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <utility>
#include <vector>
#define ll long long
#define pll pair<long long,long long>
#define P pair<int,int>
#define PP pair<P,P>
#define eps 1e-4
#define It set<node>::iterator
using namespace std;
const int maxn=1e5+10;
ll mod;
struct node {
int l,r;
mutable ll val;
node(int l, int r=-1,ll val=-1):l(l),r(r),val(val) {}
bool operator< (const node& n) const {
return l<n.l;
}
};
set<node> s;
int rep[maxn],n,m;
It split(int idx) {
It it=s.lower_bound(node(idx));
if (it!=s.end()&&it->l==idx) return it;
--it;
int l=it->l,r=it->r,val=it->val;
s.erase(it);
s.insert(node(l,idx-1,val));
return s.insert(node(idx,r,val)).first;
}
void assign(int l, int r, int val) {
It it2=split(r+1),it1=split(l);
s.erase(it1,it2);
s.insert(node(l,r,val));
}
void add(int l, int r, ll val) {
It it2=split(r+1),it1=split(l);
while (it1!=it2) {
it1->val+=val;
it1->val%=mod;
it1++;
}
}
void Mul(int l, int r, ll val) {
It it2=split(r+1),it1=split(l);
while (it1!=it2) {
it1->val*=val;
it1->val%=mod;
it1++;
}
}
ll solve(int l, int r) {
It it2=split(r+1);
It it1=split(l);
ll res=0;
while (it1!=it2) {
res+=it1->val*(it1->r-it1->l+1);
res%=mod;
it1++;
}
return res;
}
int main() {
// memset(rep,-1,sizeof(rep));
scanf("%d%d%lld",&n,&m,&mod);
for (int i=1; i<=n; i++) {
ll num;
scanf("%lld",&num);
s.insert(node(i,i,num));
}
s.insert(node(n+1));
int Last=n+1;
while (m--) {
int op,l,r;
ll k;
scanf("%d",&op);
if (op==1) {
scanf("%d%d%lld",&l,&r,&k);
add(l,r,k);
} else if (op==2) {
scanf("%d%d%lld",&l,&r,&k);
Mul(l,r,k);
} else if (op==3) {
scanf("%d%d%lld",&l,&r,&k);
assign(l,r,k);
} else if (op==4) {
scanf("%lld",&k);
It it=s.lower_bound(node(Last));
s.erase(it);
s.insert(node(Last,Last,k));
Last+=1;
s.insert(node(Last));
} else if (op==5) {
scanf("%d%d",&l,&r);
printf("%lld\n",solve(l,r));
}
}
return 0;
}
查看11道真题和解析