全球变暖
- 用 b f s bfs bfs 求出所有的连通块,并且对每个连通块进行编号,因为数据到 1000 1000 1000,因此连通块至多 1 e 6 1e6 1e6块。
- 将所有会被淹没的陆地都变成海洋。
- 计算剩余的块数,只要看原来的连通块的编号是否还存在没有被淹没的陆地就好。
- 将原来的块数减去剩余的块数即可。
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
int num[1000][1000];
int n,cnt;
bool vis[N];
char g[1000][1000];
bool change[1000][1000];
int dx[4]={1,-1,0,0},dy[4]={0,0,1,-1};
struct Node{ int x,y;};
void bfs(int x,int y){
queue<Node>q;
q.push({x,y});
num[x][y]=cnt;
while(!q.empty()){
Node cur=q.front();q.pop();
for(int i=0;i<4;i++){
int nx=cur.x+dx[i],ny=cur.y+dy[i];
if(nx<0||ny<0||nx>=n||ny>=n)continue;
if(g[nx][ny]=='.'||num[nx][ny])continue;
q.push({nx,ny});
num[nx][ny]=cnt;
}
}
}
int main(){
cin>>n;
for(int i=0;i<n;i++)for(int j=0;j<n;j++)cin>>g[i][j];
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(g[i][j]=='#'&&!num[i][j]){
cnt++;
bfs(i,j);
}
}
}
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(g[i][j]=='#'){
for(int k=0;k<4;k++){
int nx=i+dx[k],ny=j+dy[k];
if(nx<0||ny<0||nx>=n||ny>=n||g[nx][ny]=='#')continue;
change[i][j]=true;break;
}
}
}
}
int ori_cnt=cnt;cnt=0;
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(g[i][j]=='#'&&!change[i][j])vis[num[i][j]]=1;
}
}
for(int i=1;i<=ori_cnt;i++){
if(vis[i])cnt++;
}
cout<<ori_cnt-cnt<<endl;
return 0;
}
乘积最大
选择问题考虑贪心,按绝对值从大到小排序,而且看题目是要我们求最大值之后再去取模,所以我们一定是把数选好了之后,将选好的数直接相乘然后取模的,无法边算边选。
因为有负数和选定个数的限制,因此应该是奇偶性的问题。
1. 若k==n,直接操作
2. 看前k个数(因为k!=n,若存在0,0必在第n个位置,因此前k个均不含0了,但是可能有很多个0呀)
(1)若有偶数个负数:直接操作
(2)若有奇数个负数:
①. 若后n-k个有正数,取后n-k个的第一个正数而删除前k个的最后一个负数
②. 若后n-k个有负数,前k个有正数,取后n-k个的第一个负数,删除前k个的最后一个正数
③. 否则结果必为非正数,直接选后k个相乘
第一次提交发现ans乘正数和负数的取模方式是不一样的,就wa了,第二次发现ans1,ans2没有初始化,顺便发现ans1,ans2的位置写反了…得意的小技巧是:在判断大小的时候避免了浮点数计算,即判断①,②不同取法大小的时候用十字相乘法比较(好吧挺幼稚的)。
代码有点长,如下:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1E5+10;
const int mod=1000000009;
int n,k;
ll a[N];
ll mul(ll x,ll y){
if(y<0)return (0-((0-x*y) % mod));
else return x*y%mod;
}
bool cmp(ll x,ll y){
return abs(x)>abs(y);
}
int main(){
cin>>n>>k;
int pos=0,neg=0,k_pos=0,k_neg=0;
for(int i=1;i<=n;i++){
cin>>a[i];
if(a[i]>0)pos++;
if(a[i]<0)neg++;
}
sort(a+1,a+1+n,cmp);
if(k==n){
ll ans=1;
for(int i=1;i<=k;i++)ans=mul(ans,a[i]);
cout<<ans<<endl;
}
else {
ll last_neg=0,last_pos=0,fir_neg=0,fir_pos=0;
for(int i=1;i<=k;i++){
if(a[i]>0){
k_pos++;
last_pos=a[i];
}
else if(a[i]<0){
k_neg++;
last_neg=a[i];
}
}
for(int i=k+1;i<=n;i++){
if(fir_neg==0&&a[i]<0)fir_neg=a[i];
if(fir_pos==0&&a[i]>0)fir_pos=a[i];
}
if(k_neg%2==0){
ll ans=1;
for(int i=1;i<=k;i++)ans=mul(ans,a[i]);
cout<<ans<<endl;
}
else {
double ans=0;//ans是拿去舍掉的
int fl=0;
ll ans1=0,ans2=0;
if(fir_neg!=0&&last_pos!=0){
ans1=fir_neg,ans2=last_pos;
}
if(fir_pos!=0&&last_neg!=0){
if(-1*fir_neg*last_neg>-1*fir_pos*last_pos)//十字相乘
ans1=fir_pos,ans2=last_neg;
}
if(ans1==0&&ans2==0){
ll ans=1;
for(int i=n;i>n-k;i--)ans=mul(ans,a[i]);
cout<<ans<<endl;
}
else {
ll ans=1;
for(int i=1;i<=k;i++){
if(a[i]!=ans2)ans=mul(ans,a[i]);
}
ans=mul(ans,ans1);
cout<<ans<<endl;
}
}
}
return 0;
}