0
点赞
收藏
分享

微信扫一扫

洛谷P6974题解

i奇异 2022-02-18 阅读 51
c++算法

题目传送门

题目大意:一个矩阵,每次查询一行或一列的和,再将其删去。

大致思路如下:

既然行与列对称,我们只考虑删行即可。如果删掉了第 i i i 行,很明显地,第 i i i 行与第 j j j 列只有 ( i , j ) (i,j) (i,j) 一个交点,而它的值就是行号 ( i ) (i) (i) 加列号 ( j ) (j) (j),所以这一操作会让第 j j j 列的元素和减少 i + j i+j i+j

这样的话,可以展开以下推导:

我们还是只分析行。假设所有删列操作的列号分别为 x 1 , x 2 , … , x k x_1,x_2,\dots,x_k x1,x2,,xk

易得第 i \texttt{i} i 行的初始元素和为

( i + 1 ) + ( i + 2 ) + ⋯ + ( i + n ) = ( i + 1 + i + n ) ∗ n / 2 (i+1)+(i+2)+\dots+(i+n)=(i+1+i+n)*n/2 (i+1)+(i+2)++(i+n)=(i+1+i+n)n/2

= i ∗ n + n ∗ ( n + 1 ) / 2 \kern13.5em=i*n+n*(n+1)/2 =in+n(n+1)/2

那么,根据上面推导的规律, k \texttt{k} k 次删除之后,元素和就会变为下面这个柿子:

i ∗ n − ( i + x 1 ) − ( i + x 2 ) − ⋯ − ( i + x k ) + n ∗ ( n + 1 ) / 2 i*n-(i+x_1)-(i+x_2)-\dots-(i+x_k)+n*(n+1)/2 in(i+x1)(i+x2)(i+xk)+n(n+1)/2,化简得

i ∗ ( n − k ) − ( x 1 + x 2 + ⋯ + x n ) + n ∗ ( n + 1 ) / 2 i*(n-k)-(x_1+x_2+\dots+x_n)+n*(n+1)/2 i(nk)(x1+x2++xn)+n(n+1)/2

所以,我们只需要两个变量保存剩余列数 & \& & 每次删列的索引和即可直接计算出剩余元素和了。

巴拉巴拉讲了一大堆,该 跑路 贴标程了:

#include<bits/stdc++.h>
using namespace std;
long long n,m,r,l,a,b,x,sum;//l保存删列索引和,r保存删行索引和,
bool vis1[1000001],vis2[1000001];//a保存剩余列数,b保存剩余行数
char c;
int main(){
	cin>>n>>m;
	sum=(n+1)*n/2,a=b=n;
	for(int i=1;i<=m;i++){
		cin>>c>>x;
		if(c=='R'){
			if(vis1[x])cout<<0<<endl;//如果删掉了直接输出0
			else{
				vis1[x]=1;//记录这行被删了
				cout<<x*a-l+sum<<endl;//公式
				b--;
				r+=x;
			}
		}else{//同上
			if(vis2[x])cout<<0<<endl;
			else{
	        	vis2[x]=1;
				cout<<x*b-r+sum<<endl;
				a--;
				l+=x;
			}
		}
	}
    return 0;
}
举报

相关推荐

0 条评论