把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

CF1396D Rainbow Rectangles

题面传送门

3300?2300!

首先发现离散后得到 每一维都是\(O(n)\)的,如果枚举一个角,那么剩下的会分成\(O(n)\)段,时间复杂度至少\(O(n^3)\)因此不大行。

考虑枚举矩形的左右边界,然后去确定上下边界。

考虑开一颗线段树,每个叶子节点维护至少往后到哪里才能合法,最后用\(L(L+1)\)减去即得到合法的区间个数。

考虑从后往前逐渐删点,可以发现每次删掉一个点,会将这个点到这个点同色前驱的一段区间内的值与这个点同色后继取max,同时这个值单调,因此可以直接线段树上二分出一段区间修改即可。

时间复杂度\(O(n^2\log n)\)实际上还跑得挺快。

code:

#include<bits/stdc++.h>
#define Gc() getchar() 
#define Me(x,y) memset(x,y,sizeof(x))
#define Mc(x,y) memcpy(x,y,sizeof(x))
#define d(x,y) ((m)*(x-1)+(y))
#define R(n) (rnd()%(n))
#define Pc(x) putchar(x)
#define LB lower_bound
#define UB upper_bound
#define PB push_back
using ll=long long;using db=double;using lb=long db;using ui=unsigned;using ull=unsigned ll;
using namespace std;const int N=2e3+5,M=N*4+5,K=1e5+5,mod=1e9+7,Mod=mod-1;const db eps=1e-5;
int n,m,L,R[N],Nx[N],Xh,Ny[N],Yh,X[N],Y[N],C[N],g[N],Ct;ll Ans;
struct Node{int y,c;};vector<Node> S[N];vector<int> P[N];multiset<int> f[N];
namespace Tree{
	#define ls v<<1
	#define rs v<<1|1 
	ll Fl[M],Sum[M],Si[M],Mx[M],Mi[M];void Up(int v){Sum[v]=Sum[ls]+Sum[rs];Mx[v]=Mx[rs];Mi[v]=Mi[ls];}void PF(int v,ll w){Mx[v]=Mi[v]=Fl[v]=w;Sum[v]=w*Si[v];}void P(int v){Fl[v]&&(PF(ls,Fl[v]),PF(rs,Fl[v]),Fl[v]=0);}
	void BD(int l=2,int r=Yh,int v=1){Fl[v]=0;Si[v]=Ny[r]-Ny[l-1];if(l==r)return PF(v,Ny[R[l]+1]);int m=l+r>>1;BD(l,m,ls);BD(m+1,r,rs);Up(v);}
	void Push(int x,int y,int z,int l=2,int r=Yh,int v=1){if(Mi[v]>=z) return;if(x<=l&&r<=y&&Mx[v]<=z) return PF(v,z);int m=l+r>>1;P(v);x<=m&&(Push(x,y,z,l,m,ls),0);y>m&&(Push(x,y,z,m+1,r,rs),0);Up(v);}
	#undef ls
	#undef rs
}
int main(){
	freopen("1.in","r",stdin);
	int i,j;scanf("%d%d%d",&n,&m,&L);for(i=1;i<=n;i++) scanf("%d%d%d",&X[i],&Y[i],&C[i]),Nx[++Xh]=X[i],Ny[++Yh]=Y[i];
	Nx[++Xh]=-1;Nx[++Xh]=L;Ny[++Yh]=-1;Ny[++Yh]=L;sort(Nx+1,Nx+Xh+1);sort(Ny+1,Ny+Yh+1);Xh=unique(Nx+1,Nx+Xh+1)-Nx-1;Yh=unique(Ny+1,Ny+Yh+1)-Ny-1;
	for(i=1;i<=n;i++) S[X[i]=LB(Nx+1,Nx+Xh+1,X[i])-Nx].PB((Node){Y[i]=LB(Ny+1,Ny+Yh+1,Y[i])-Ny,C[i]});
	for(i=1;i<=m;i++) f[i].insert(1),f[i].insert(Yh);for(i=Xh-1;i>1;i--){//cerr<<i<<'\n';
		for(Node p:S[i]) P[p.y].PB(p.c);for(j=i;j<Xh;j++) for(Node p:S[j]) f[p.c].insert(p.y);
		Ct=0;Me(g,0);R[Yh]=Yh-1;for(j=Yh-1;j>1;j--){
			R[j]=R[j+1];for(int p:P[j]) Ct+=!g[p],g[p]++;
			while(Ct==m){for(int p:P[R[j]]) g[p]--,Ct-=!g[p];R[j]--;}
		}Tree::BD();for(j=Xh-1;j>=i;j--){
			Ans+=(1ll*(L+1)*L-Tree::Sum[1])%mod*(Nx[i]-Nx[i-1])%mod*(Nx[j+1]-Nx[j])%mod;
			for(Node p:S[j]){
				f[p.c].erase(f[p.c].LB(p.y));auto h=f[p.c].LB(p.y);int La=*h;La^p.y&&(Tree::Push(*--h+1,p.y,Ny[La]),0);
			}
		}
	}printf("%lld\n",Ans%mod);
}
posted @ 2022-10-19 20:11  275307894a  阅读(29)  评论(0编辑  收藏  举报
浏览器标题切换
浏览器标题切换end