在一个 方格(下标为 ).
有 个 豆,第 个坐标为 ,颜色为 ,总共有 种.
问有多少个矩形能包含所有的颜色. .
显然,我们可以把豆放在左下角,那么坐标范围改为
.
然后呢,
条横竖线把方格划分为
块,显然每两块之间的包含情况相同.(忽略边界)
暴力做法当然是 的枚举啦,这个想必大家都会,但是这个还有可能 .
换个思路,如果我们确定了两个
坐标的范围,然后求有多少种合法的
一样可以求解.
因为本质不同的
可以视为
,所以枚举
的区间是
.
我们对每一个本质相同的
都求出一个上界
,满足
是一种合法的
区间.
显然这个上界单调不降,每次
区间发生变化的时候肯定是把边界的踢出去,此时我们需要更改
,
容易发现它只会修改一个后缀,那么我们用线段树就可以
修改.(本质上是一个单调序列取
).
#include<bits/stdc++.h>
#define lc (x<<1)
#define rc (x<<1|1)
using namespace std;
typedef long long ll;
const int N=2055,mod=(int) 1e9+7;
void qr(int &x) {scanf("%d",&x);}
int n,m,L,last[N],col[N],ys[N],tot,vis[N];
struct P {int x,y,c,i; } a[N];
bool cmpx(P a,P b) {return a.x<b.x;}
bool cmpy(P a,P b) {return a.y<b.y; }
struct Q {
int l[N],r[N];
void del(int x) {
l[r[x]]=l[x];
r[l[x]]=r[x];
}
} q,nq;
struct node {
int mn,mx,s,tag;
node(int a=0,int b=0,int c=0,int d=0) {mn=a; mx=b; s=c; tag=d; }
node operator+(node b) const {
return node(min(mn,b.mn),max(mx,b.mx),(s+b.s)%mod,0);
}
} tr[N*2]; int f[N];
void upd(int x,int l,int r,ll t) {tr[x]=node(t,t,1LL*(ys[r]-ys[l-1])*t%mod,t); }
void bt(int x,int l,int r) {
if(l==r) {upd(x,l,r,f[l]); return ;}
int mid=(l+r)/2; bt(lc,l,mid); bt(rc,mid+1,r); tr[x]=tr[lc]+tr[rc];
}
void change(int x,int l,int r,int L,ll t) {
if(tr[x].mn>=t) return;
if(tr[x].mx<=t&&l==L) {upd(x,l,r,t); return ;}
int mid=(l+r)/2;
if(tr[x].tag) {
upd(lc,l ,mid,tr[x].tag);
upd(rc,mid+1,r,tr[x].tag);
tr[x].tag=0;
}
if(L<=mid) change(lc,l,mid,L,t);
change(rc,mid+1,r,max(mid+1,L),t);
tr[x]=tr[lc]+tr[rc];
}
int main() {
qr(n);; qr(m); qr(L);
for(int i=1;i<=n;i++)qr(a[i].x),qr(a[i].y),qr(a[i].c);
sort(a+1,a+n+1,cmpy); a[0].x=a[0].y=-1; a[n+1].x=a[n+1].y=L;
for(int i=0;i<=n+1;i++) ys[i]=a[i].y,a[i].i=i;
for(int i=1;i<=n;i++) {
int l=nq.l[i]=last[a[i].c]; last[a[i].c]=i;
nq.r[i]=n+1; nq.r[l]=i;
}
sort(a+1,a+n+1,cmpx); ll ans=0;
for(int i=1;i<=n;i++) {
if(a[i].x^a[i-1].x) {
for(int j=1;j<i;j++) col[a[j].i]=0;
for(int j=i;j<=n;j++) col[a[j].i]=a[j].c;
for(int l=1,r=1;l<=n;l++) {
for( ;r<=n&&tot<m;r++) if(col[r]&&!vis[col[r]]++) tot++;
f[l]=(tot<m)?L:ys[r-1];if(col[l]&&!--vis[col[l]]) tot--;
}
q=nq; bt(1,1,n);
for(int j=n;j>=i;j--) {
ans += (1LL*(ys[n]+1)*L-tr[1].s)%mod*(a[i].x-a[i-1].x)%mod*(a[j+1].x-a[j].x)%mod;
int id=a[j].i,l=q.l[id],r=q.r[id];
change(1,1,n,l+1,ys[r]); q.del(id);
}
ans%=mod;
}
nq.del(a[i].i);
}
printf("%lld\n",ans); return 0;
}