Live2D

ETO的公开赛T4《对抗水滴》 题解(BY 萌萌哒123456 )

题意:

给你一个\(n*n\)的矩阵A,其中有\(T\)个元素不为零。定义矩阵内元素\((x,y)\)的能量值

\(E[x][y]=\sum_{i=1}^{x}\sum_{j=1}^{y}[A[i][j]>0]\)

\(m\)个询问\((x,y,d)\),每次询问是否存在二元组\((x',y')\)满足 \(x'=x\)\(y'=y\) ,使得

\(E[x'][y']*A[x'][y']>=d\)

如果存在,则\(ans1++,ans2+=min(E[x'][y'])\)。否则将 \(A[x][y]\) 修改为零。最后输出\(ans1\)\(ans2\)

题解:

暴力出奇迹!

我们注意到这道题的时限是5秒,并且还开O2,因此我们只需要打一个优雅的暴力然后卡一波常数即可通过此题。

我们对每一行和每一列都开一个树状数组,维护第\(i\)行(列)前j个数中,不为零的元素个数。对于每一个询问,我们暴力枚举每一个可行元素,用树状数组查询其能量值,求出符合条件的最小能量值。对于修改,我们只需要修改两个树状数组即可。时间复杂度\(O(mnlogn)\)

代码如下:

#include<bits/stdc++.h>
#define LL long long
using namespace std;

const int N=1000+50,M=1000000+50;
int n,T,m,a[N][N],R[N][N],C[N][N];
LL d[M];

inline int read(){
	int x=0,f=1;char ch;
	for(ch=getchar();!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
	for(;isdigit(ch);ch=getchar())x=(x<<3)+(x<<1)+ch-'0';
	return x*f;
}
inline int lowbit(int x){
	return x&(-x);
}
inline void Add(int F[],int x,int val){
	for(;x<=n;x+=lowbit(x))F[x]+=val;
}
inline int Query(int F[],int x){
	int ans=0;
	for(;x;x-=lowbit(x))ans+=F[x];
	return ans;
}

int main(){
	n=read(),T=read();
	for(register int i=1;i<=T;++i){
		int x=read(),y=read(),w=read();
		a[x][y]=w;
		Add(R[x],y,1);Add(C[y],x,1);
	}
	m=read();
	for(register int i=1;i<=m;++i)d[i]=1LL*read();
	int ans1=0;LL ans2=0;
	for(register int i=1;i<=m;++i){
		int x=read(),y=read();
		int flag=0,mincost=1e9;
		for(register int j=1,cost=0;j<=n;++j){
			cost+=Query(R[j],y);
			if(a[j][y] && 1LL*cost*a[j][y]>=d[i]){
				flag=1;mincost=cost;break;
			}
		}
		for(register int j=1,cost=0;j<=n;++j){
			cost+=Query(C[j],x);
			if(a[x][j] && 1LL*cost*a[x][j]>=d[i]){
				flag=1;mincost=min(mincost,cost);break;
			}
		}
		if(flag)++ans1,ans2+=1LL*mincost;
		else{
			if(a[x][y]){
				a[x][y]=0;
				Add(R[x],y,-1);Add(C[y],x,-1);
			}
		}
	}
	printf("%d\n%lld\n",ans1,ans2);
	return 0;
}
posted @ 2018-09-27 21:48  ztz11  阅读(426)  评论(2编辑  收藏  举报