P8441
我们考虑使用 std::set 维护每种颜色出现的连续段。
下面对于一个连续段使用
对于一次询问,我们钦定一种颜色的贡献由
那么若现在在颜色
对于这样的矩形加单点查形式,我们考虑使用树套树或者 KD 树维护,由于颜色段均摊,复杂度是
但是本题的空间限制不能满足树套树
但是我们发现本题并没有强制在线,所以把所有操作离线下来进行 CDQ 分治即可。
时间复杂度
Code
#include<set>
#include<cassert>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
namespace EMT{
typedef long long ll;typedef double db;
#define pf printf
#define F(i,a,b) for(int i=a;i<=b;i++)
#define D(i,a,b) for(int i=a;i>=b;i--)
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
const int N=1e5+10;
struct qs{int opt,x,l,r,v;friend bool operator <(qs a,qs b){return a.x<b.x;}}q[N*10];
int n,m,qcnt;
struct BIT{
ll t[N];
inline void add(int x,int v){while(x<=n)t[x]+=v,x+=x&-x;}
inline void add(int l,int r,int v){add(l,v),add(r+1,-v);}
inline ll ask(int x){ll ans=0;while(x)ans+=t[x],x-=x&-x;return ans;}
}bit;
ll ans[N];
struct dp{int l,r;friend bool operator <(dp a,dp b){return a.l<b.l;}};
std::set<dp>s[N];
inline void add(int l,int r,int ql,int qr,int v){
q[++qcnt]={1,l,ql,qr,v},
q[++qcnt]={1,r+1,ql,qr,-v};
}
inline int ask(std::set<dp> &s,std::set<dp>::iterator it){
if(it==s.begin())return 1;it--;return it->r+1;
}
inline void ins(int v,int l,int r){
if(1){
auto it=s[v].upper_bound({r,r});
if(it!=s[v].begin()){
it--;
if(it->r>=r&&it->l<=l)return;
}
}
auto it=s[v].upper_bound({r,r});bool fl=0;
if(it!=s[v].end()){
add(ask(s[v],it),it->r,it->l,n,-v);
if(it->l==r+1){r=it->r;it=s[v].erase(it);fl=1;}
}
while(it!=s[v].begin()){
it--;
if(l<=it->l&&it->r<=r){add(ask(s[v],it),it->r,it->l,n,-v);it=s[v].erase(it);continue;}
if(it->r+1<l)break;
if(it->r+1==l){add(ask(s[v],it),it->r,it->l,n,-v);l=it->l;s[v].erase(it);break;}
if(it->r>r){add(ask(s[v],it),it->r,it->l,n,-v);r=it->r;it=s[v].erase(it);continue;}
assert(it->l<=l);l=it->l;add(ask(s[v],it),it->r,it->l,n,-v);it=s[v].erase(it);break;
}
if(!fl){
it=s[v].upper_bound({r,r});
if(it!=s[v].end())add(r+1,it->r,it->l,n,v);
}
it=s[v].insert({l,r}).first;add(ask(s[v],it),r,l,n,v);
}
inline void cdq(int l,int r){
if(l==r)return;
int mid=(l+r)>>1;
cdq(l,mid),cdq(mid+1,r);
std::sort(q+l,q+mid+1),
std::sort(q+mid+1,q+r+1);
int j=l;
F(i,mid+1,r){
while(q[i].x>=q[j].x&&j<=mid){
if(q[j].opt==1)bit.add(q[j].l,q[j].r,q[j].v);
j++;
}if(q[i].opt==2)ans[q[i].v]+=bit.ask(q[i].r);
}
while(j>l){
j--;
if(q[j].opt==1)bit.add(q[j].l,q[j].r,-q[j].v);
}
}
inline short main(){
n=read();m=read();
memset(ans,-1,sizeof(ans));
F(i,1,m){
int opt=read(),l=read(),r=read();
if(opt==1){ins(read(),l,r);}
else q[++qcnt]={2,l,r,r,i},ans[i]=0;
}
cdq(1,qcnt);
F(i,1,m)if(~ans[i])pf("%lld\n",ans[i]);
return 0;
}
}
signed main(){return EMT::main();}