首先这个离谱的询问一:
关于不同的数的和,可以构造求出每个点
(
x
,
S
x
)
(x,S_x)
(x,Sx)的前面第一个
(
y
,
S
y
=
S
x
)
(y,S_y =S_x)
(y,Sy=Sx),那么把
(
y
,
x
)
(y,x)
(y,x)看做一个二维平面上的点,那么对
[
l
,
r
]
[l,r]
[l,r]中不同数的个数即为
y
<
l
,
l
≤
x
≤
r
y \lt l , l \leq x \leq r
y<l,l≤x≤r的点数。
那么在没有插入删除的情况下这就是一个三维偏序(注意128MB卡内存,可以用离线的方法树状数组套树状数组空间 O ( n log n ) O(n\log n) O(nlogn)求解。)
有插入删除的情况,先离线用平衡树模拟一遍转化为没有插入删除即可。
A C C o d e \mathcal AC Code ACCode
#include<bits/stdc++.h>
#define maxn 200005
#define rep(i,j,k) for(int i=(j),LIM=(k);i<=LIM;i++)
#define per(i,j,k) for(int i=(j),LIM=(k);i>=LIM;i--)
#define LL long long
#define Ct const
#define mod 1000000007
#define iv6 166666668ll
using namespace std;
char Start;
namespace IO{
char cb[1<<16],*cs=cb,*ct=cb;
#define getc() (cs==ct&&(ct=(cs=cb)+fread(cb,1,1<<16,stdin),cs==ct)?0:*cs++)
void read(int &res){
char ch;
for(;!isdigit(ch=getc()););
for(res=ch-'0';isdigit(ch=getc());res=res*10+ch-'0');
}
}
using IO::read;
int n,q;
namespace Solver1{
int a[2 * maxn] , b[2 * maxn];
void solve(){
rep(i,1,n) read(a[i]);
for(int op,x,y;q--;){
read(op),read(x);
if(op == 3){
rep(i,x,n-1) a[i] = a[i+1];
n--;
continue;
}
read(y);
if(op == 2)
a[x] = y;
if(op == 4){
per(i,n+1,x+2) a[i] = a[i-1];
a[x+1] = y;
}
if(op == 1 || op == 5){
int cnt = 0;
rep(i,x,y) b[++cnt] = a[i];
sort(b+1,b+1+cnt);
cnt = unique(b+1,b+1+cnt) - b - 1;
LL ans = 0;
if(op == 1){
LL s0 = 1 , s1 = 0 , s2 = 0;
rep(i,1,cnt)
ans = (ans + s2 * b[i]) % mod ,
s2 = (s2 + s1 * b[i]) % mod ,
s1 = (s1 + s0 * b[i]) % mod ;
}
else{
ans = cnt;
}
printf("%lld\n",ans);
}
}
}
}
set<int>st[maxn];
int sb[maxn];
int dat[maxn][3],A[maxn],N,B[maxn];
void add(int &u,int v){ (u += v) >= mod && (u -= mod); }
#define pii pair<int,int>
#define mp make_pair
#define pb push_back
namespace BIT{
#define maxp 100000 * 20
int ans[maxn][4];
vector<pair<int,int> >Q[maxn];
int tr[4][maxn],vis[maxn],tim;
void upd(int u,int v,int *tr){
for(;u<=N;u+=u&-u){
if(vis[u] != tim){
vis[u] = tim;
rep(i,0,3)
BIT::tr[i][u] = 0;
}
add(tr[u],v);
}
}
int qry(int u,int*tr){ int r=0;for(;u;u-=u&-u) if(vis[u] == tim) add(r,tr[u]);return r; }
void Add(int a,int b,int v,int val){
a++;
int B = b;
val *= v;
for(;b <= N;b += b&-b)
Q[b].pb(mp(a,val)) , Q[b].pb(mp(B+1,-val));
}
void del(int u){
if(B[u] == -1) return;
set<int>&s = st[lower_bound(sb+1,sb+1+sb[0],B[u])-sb];
set<int>::iterator it = s.lower_bound(u) , it2 = it;
if(it == s.begin())
Add(0,u,-1,B[u]);
else
it--,Add(*it,u,-1,B[u]),it++;
if((++it2) != s.end()){
Add(u,*it2,-1,B[u]);
if(it == s.begin())
Add(0,*it2,1,B[u]);
else
it--,Add(*it,*it2,1,B[u]),it++;
}
s.erase(it);
B[u] = -1;
}
void ins(int u,int x){
B[u] = x;
set<int>&s = st[lower_bound(sb+1,sb+1+sb[0],B[u])-sb];
set<int>::iterator it = s.insert(u).first , it2 = it;
if(it == s.begin())
Add(0,u,1,B[u]);
else
it--,Add(*it,u,1,B[u]),it++;
if((++it2) != s.end()){
Add(u,*it2,1,B[u]);
if(it == s.begin())
Add(0,*it2,-1,B[u]);
else
it--,Add(*it,*it2,-1,B[u]),it++;
}
}
void solve(){
rep(i,1,N) if(B[i] != -1) ins(i,B[i]);
rep(i,1,q) if(dat[i][0] == 1 || dat[i][0] == 5){
for(int u=dat[i][2];u;u-=u&-u)
Q[u].pb(mp(i,0));
}
else{
if(dat[i][0] == 3) del(dat[i][1]);
if(dat[i][0] == 2) del(dat[i][1]) , ins(dat[i][1] , dat[i][2]);
if(dat[i][0] == 4) del(dat[i][1]) , ins(dat[i][1] , dat[i][2]);
}
rep(i,1,N){
++tim;
for(auto u:Q[i]){
if(u.second == 0){
rep(j,0,3) add(ans[u.first][j] , qry(dat[u.first][1],tr[j]));
}
else{
int v = 1;
if(u.second < 0) v = mod-1 , u.second = -u.second;
rep(j,0,3){
upd(u.first,v,tr[j]);
v = 1ll * v * u.second % mod;
}
}
}
}
rep(i,1,q) if(dat[i][0] == 1 || dat[i][0] == 5){
if(dat[i][0] == 5) printf("%d\n",ans[i][0]);
else {
printf("%d\n",(((ans[i][1]*1ll*ans[i][1]%mod*ans[i][1])+2ll*ans[i][3]-3ll*ans[i][2]*ans[i][1])%mod*iv6%mod+mod)%mod);
}
}
}
}
namespace Treap{
int sz[maxn],key[maxn],lc[maxn],rc[maxn],sm[maxn],val[maxn],rk[maxn],rt,tot;
void upd(int u){ sz[u] = sz[lc[u]] + sz[rc[u]] + 1 , sm[u] = sm[lc[u]] + sm[rc[u]] + val[u]; }
void merge(int &u,int l,int r){
if(!l || !r) return (void)(u = l+r);
if(key[l] < key[r]) u = l , merge(rc[u] , rc[l] , r);
else u = r , merge(lc[u] , l , lc[r]);
upd(u);
}
void split_sz(int u,int &l,int &r,int rk){
if(!u) return (void)( l = r = 0);
if(sz[lc[u]] + 1 <= rk) l = u , split_sz(rc[u],rc[l],r,rk - sz[lc[u]]-1);
else r = u , split_sz(lc[u],l,lc[r],rk);
upd(u);
}
void split_sm(int u,int &l,int &r,int rk){
if(!u) return (void)( l = r = 0);
if(sm[lc[u]] + val[u] <= rk) l = u , split_sm(rc[u],rc[l],r,rk - sm[lc[u]] - val[u]);
else r = u , split_sm(lc[u],l,lc[r],rk);
upd(u);
}
int getpt(int x){
int a,b,c;
split_sm(rt,a,b,x-1);
split_sz(b,b,c,1);
int r = b;
merge(rt,a,b) , merge(rt,rt,c);
return r;
}
void dfs(int u){
if(!u) return;
static int tim = 0;
dfs(lc[u]);
rk[u] = ++tim;
dfs(rc[u]);
}
void solve(){
rep(i,1,n) val[i] = sz[i] = sm[i] = 1 , key[i] = rand() , merge(rt,rt,i);
tot = n;
rep(i,1,q){
int a,b,c,d;
read(dat[i][0]),read(dat[i][1]);
if(dat[i][0] == 3){
split_sm(rt,a,b,dat[i][1]-1);
split_sz(b,b,c,1);
val[b] = sm[b] = 0;
dat[i][1] = b;
merge(rt,a,b) , merge(rt,rt,c);
continue;
}
read(dat[i][2]);
if(dat[i][0] == 1 || dat[i][0] == 5){
dat[i][1] = getpt(dat[i][1]);
dat[i][2] = getpt(dat[i][2]);
}
if(dat[i][0] == 2){
dat[i][1] = getpt(dat[i][1]);
}
if(dat[i][0] == 4){
split_sm(rt,a,b,dat[i][1]);
dat[i][1] = ++tot;
key[tot] = rand() , sm[tot] = sz[tot] = val[tot] = 1;
merge(rt,a,tot) , merge(rt,rt,b);
}
}
dfs(rt);
rep(i,1,q){
if(dat[i][0] == 1 || dat[i][0] == 5)
dat[i][1] = rk[dat[i][1]] , dat[i][2] = rk[dat[i][2]];
else dat[i][1] = rk[dat[i][1]];
}
memset(B,-1,sizeof B);
rep(i,1,n) B[rk[i]] = A[i];
N = tot;
}
}
char End;
int main(){
read(n),read(q);
rep(i,1,n) read(A[i]);
Treap::solve();
rep(i,1,n) sb[++sb[0]] = A[i];
rep(i,1,q) if(dat[i][0] == 2 || dat[i][0] == 4)
sb[++sb[0]] = dat[i][2];
sort(sb+1,sb+1+sb[0]);
sb[0] = unique(sb+1,sb+1+sb[0]) - sb - 1;
BIT::solve();
}