Yet Another Range Query Problem 题解
我们考虑这个东西并不好维护,我们可以离线下来差分求解答案,我们又发现这个\(\min*\max\)难以维护,那么我们开一个\(5\times5\)的矩阵,像这样定义:\([\sum \min,\sum \max, \sum{\min \times \max} , history~sum,size]\),我们发现我们把一个区间统一赋值成一个\(\min\)或者\(\max\)可以给他乘上一个矩阵,以\(\min\)举例,假设我们要更改为\(x\)。
\[\begin{bmatrix}
0& 0 & 0 & 0 &0 \\
0& 1 & x & 0 &0 \\
0& 0 & 0 & 0 &0 \\
0& 0 & 0 & 1 &0 \\
x& 0 & 0 & 0 &1
\end{bmatrix}
\]
统计历史和也显然可以使用矩阵进行维护。
鉴于卡常后可读性为0,挂上一版卡常前的代码供参考。
代码:
#include <bits/stdc++.h>
#define int long long
#define lid (id<<1)
#define rid (id<<1|1)
#define mid ((l+r)>>1)
using namespace std;
const int modd=1e9+7;
const int maxn=2e5+10;
struct node{
int a[5][5];
void init(){
for(int i=0;i<5;i++){
for(int j=0;j<5;j++){
a[i][j]=0;
}
}
return;
}
const node operator *(const node &q)const{
node qw;
qw.init();
for(int i=0;i<5;i++){
for(int j=0;j<5;j++){
for(int k=0;k<5;k++){
qw.a[i][j]=(qw.a[i][j]+a[i][k]*q.a[k][j])%modd;
}
}
}
return qw;
}
const node operator +(const node &q)const{
node qw;
qw.init();
for(int i=0;i<5;i++){
for(int j=0;j<5;j++){
qw.a[i][j]=a[i][j]+q.a[i][j];
qw.a[i][j]=qw.a[i][j]>=modd?qw.a[i][j]-modd:qw.a[i][j];
}
}
return qw;
}
}chu,minn,maxx;
struct edge{
node lazy;
node val;
bool tag;
}tree[maxn<<2];
int n,m,ans[maxn],a[maxn],x,y,xx,yy,tp1,st1[maxn],tp2,st2[maxn];
vector<pair<int,pair<int,int> > >Q[maxn];
inline void push_tag(int id,node q){
if(tree[id].tag){
tree[id].lazy=tree[id].lazy*q;
}
else{
tree[id].lazy=q;
tree[id].tag=1;
}
tree[id].val=tree[id].val*q;
return;
}
inline void push_down(int id){
if(tree[id].tag){
push_tag(lid,tree[id].lazy);
push_tag(rid,tree[id].lazy);
tree[id].tag=0;
return;
}
}
inline void push_up(int id){
tree[id].val=tree[lid].val+tree[rid].val;
return;
}
inline void news(int id,int l,int r,int q){
if(l==r){
tree[id].val.a[0][4]=1;
return;
}
if(q<=mid){
news(lid,l,mid,q);
}
else{
news(rid,mid+1,r,q);
}
push_up(id);
return;
}
inline void add(int id,int l,int r,int q,int w,node qw){
if(q<=l&&r<=w){
push_tag(id,qw);
return;
}
push_down(id);
if(q<=mid){
add(lid,l,mid,q,w,qw);
}
if(w>mid){
add(rid,mid+1,r,q,w,qw);
}
push_up(id);
return;
}
inline int query(int id,int l,int r,int q,int w){
if(q<=l&&r<=w){
return tree[id].val.a[0][3];
}
push_down(id);
if(w<=mid){
return query(lid,l,mid,q,w);
}
else if(q>mid){
return query(rid,mid+1,r,q,w);
}
else{
return (query(lid,l,mid,q,w)+query(rid,mid+1,r,q,w))%modd;
}
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>n>>m;
chu.a[0][0]=1;
chu.a[1][1]=1;
chu.a[2][2]=1;
chu.a[2][3]=1;
chu.a[3][3]=1;
chu.a[4][4]=1;
minn.a[1][1]=1;
minn.a[3][3]=1;
minn.a[4][4]=1;
maxx.a[0][0]=1;
maxx.a[3][3]=1;
maxx.a[4][4]=1;
for(int i=1;i<=n;i++){
cin>>a[i];
}
for(int i=1;i<=m;i++){
cin>>x>>y>>xx>>yy;
Q[yy].push_back({i,{x,y}});
Q[xx-1].push_back({-i,{x,y}});
}
for(int i=1;i<=n;i++){
while(tp1&&a[i]<a[st1[tp1]]){
tp1--;
}
news(1,1,n,i);
minn.a[1][2]=a[i];
minn.a[4][0]=a[i];
add(1,1,n,st1[tp1]+1,i,minn);
st1[++tp1]=i;
while(tp2&&a[i]>a[st2[tp2]]){
tp2--;
}
maxx.a[0][2]=a[i];
maxx.a[4][1]=a[i];
add(1,1,n,st2[tp2]+1,i,maxx);
st2[++tp2]=i;
add(1,1,n,1,i,chu);
for(int j=0;j<Q[i].size();j++){
if(Q[i][j].first<0){
ans[-Q[i][j].first]-=query(1,1,n,Q[i][j].second.first,Q[i][j].second.second);
}
else{
ans[Q[i][j].first]+=query(1,1,n,Q[i][j].second.first,Q[i][j].second.second);
}
}
}
for(int i=1;i<=m;i++){
cout<<(ans[i]%modd+modd)%modd<<'\n';
}
return 0;
}
浙公网安备 33010602011771号