小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; }