CF627E Orchestra 题解
题目传送门:CF627E Orchestra。
这题好牛啊,可能只是我菜 /ll。
首先我们可以枚举 \(i,j\) 确定矩形的上下界,考虑如何快速计算贡献。
首先,我们将所有的点按照列为第一关键字,行为第二关键字排序,那么在枚举 \(i\) 时,就可以将所有行在 \([i,r]\) 的点,加入链表,那么每个点的贡献来自于它后 \(k-1\) 个点的列,而这个贡献相当于就是矩形左测可以在这个位置和上一个位置之间,右端点在它后 \(k-1\) 个点的列到 \(c\) 之间,乘法原理很好计算,那么我们需要动态维护每个点后 \(k-1\) 的位置即可。
考虑倒序枚举 \(j\),容易发现我们需要删去链表中的一些点,而这些点删去会使得左侧 \(k-1\) 个位置的右侧 \(k-1\) 的位置向右移动一位,暴力维护贡献增减即可,还要注意这个删去位置的右侧第一个的贡献也改变了,一个一个点暴力删除即可。
最后复杂度 \(O(r^2k)\),这里 \(r,c,n\) 同阶。
注意一些边界和清空,这题细节还是比较多的,代码一坨。
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=3010;
inline int read(){
char c=getchar();
int f=1,ans=0;
while(c<48||c>57) f=(c==45?f=-1:1),c=getchar();
while(c>=48&&c<=57) ans=(ans<<1)+(ans<<3)+(c^48),c=getchar();
return ans*f;
}
int n,m,k,len;
struct node{
int x,y;
bool operator <(const node &xx) const{
if (y==xx.y) return x<xx.x;
return y<xx.y;
}
}a[N];
int L[N],R[N],vis[N],cnt[N],c[N];
vector<int>b[N];
main(){
n=read(),m=read(),len=read(),k=read();
for (int i=1;i<=len;i++) a[i]={read(),read()};
sort(a+1,a+len+1);
int ans=0;
for (int i=1;i<=n;i++){
for (int i=0;i<=len+1;i++) L[i]=R[i]=vis[i]=c[i]=0;
for (int i=1;i<=m;i++) cnt[i]=0;
for (int i=1;i<=n;i++) b[i].clear();
int last=0;
for (int j=1;j<=len;j++)
if (i<=a[j].x){
cnt[a[j].y]++;
if (cnt[a[j].y]==1) vis[j]=1;
L[j]=last;
R[last]=j;
b[a[j].x].push_back(j);
last=j;
}
R[last]=len+1,L[len+1]=last;
int x=0,sum=0;
while(x!=len+1){
int y=x;
int tmp=k-1;
while(tmp--){
if (y==len+1) break;
y=R[y];
}
c[x]=y;
if (y!=len+1&&vis[x]) sum+=(m-a[y].y+1)*(a[x].y-a[L[x]].y);
x=R[x];
}
for (int j=n;j>=i;j--){
ans+=sum;
for (auto x:b[j]){
if (c[x]!=len+1&&vis[x]) sum-=(m-a[c[x]].y+1)*(a[x].y-a[L[x]].y);
int y=x;
int tmp=k-1;
while(tmp--){
y=L[y];
if (y==0) break;
if (c[y]!=len+1){
if (vis[y]) sum-=(m-a[c[y]].y+1)*(a[y].y-a[L[y]].y);
c[y]=R[c[y]];
if (c[y]!=len+1&&vis[y]) sum+=(m-a[c[y]].y+1)*(a[y].y-a[L[y]].y);
}
}
if (R[x]!=len+1&&vis[R[x]]){
int xx=R[x];
if (c[xx]!=len+1&&vis[xx]){
sum-=(m-a[c[xx]].y+1)*(a[xx].y-a[L[xx]].y);
sum+=(m-a[c[xx]].y+1)*(a[xx].y-a[L[x]].y);
}
}
L[R[x]]=L[x];
R[L[x]]=R[x];
}
}
}
cout <<ans;
return 0;
}

浙公网安备 33010602011771号