AtCoder Beginner Contest 241
题意:给定一个 N ∗ N N*N N∗N的矩阵,# 表示黑色,”." 表示白色,你最多可以选择两个白色的方块染成黑色,问是否可以最终有6个连续的黑色方块,(水平,垂直,对角线都算)。
因为只需6个连在一起,因此这题可以直接暴力判断,我是用bfs写的,本质上也是暴力,就是代码有点长了。
实在是丑陋!
code:
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define ios std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define int long long
#define x first
#define y second
typedef pair<int,int> pii;
//head
const int N=1e3+10,mod=998244353;
char g[N][N];
bool st[N][N];
int d[4][4]={{0,1,0,-1},{1,0,-1,0},{1,1,-1,-1},{1,-1,-1,1}};
int n;
vector<pii> v;
bool bfs(int sx,int sy,int id)
{
int cnt=0;
int sum=0;
queue<pii> q;
q.push({sx,sy});
while(q.size()){
auto t=q.front();
q.pop();
int x=t.x,y=t.y;
if(st[x][y]) continue;
sum++;
if(sum>=6) {
for(auto [i,j]:v) st[i][j]=0;
v.clear();
return 1;
}
st[x][y]=1;
v.push_back({x,y});
for(int i=0;i<4;i+=2){
int a=x+d[id][i],b=y+d[id][i+1];
if(a<0||b<0||a>=n||b>=n||(g[a][b]=='.'&&cnt>=2)) continue;
if(g[a][b]=='.') cnt++;
q.push({a,b});
}
}
for(auto [i,j]:v) st[i][j]=0;
v.clear();
return 0;
}
void work()
{
cin>>n;
for(int i=0;i<n;i++){
cin>>g[i];
}
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++){
if(bfs(i,j,k)) {
cout<<"Yes"<<endl;
return ;
}
}
}
}
}
cout<<"No"<<endl;
}
signed main()
{
int t;
//cin>>t;
t=1;
while(t--) work();
return 0;
}
题意:给定一个空序列,有三种操作:
- 插入 x 插入x 插入x
- 询问小于等于 x 的第 k 个数,若不存在输出 − 1 询问小于等于x的第k个数,若不存在输出-1 询问小于等于x的第k个数,若不存在输出−1
- 询问大于等于 x 的第 k 个数,若不存在输出 − 1 询问大于等于x的第k个数,若不存在输出-1 询问大于等于x的第k个数,若不存在输出−1
直接使用 m u l t i s e t multiset multiset即可,可以实现排序,查找,且允许重复元素出现。
注意使用其自带的二分查找。
multiset<int> s;
s.lower_bound(x);//这个是自带的,时间复杂度为O(n*logn)
lower_bound(s.begin(),s.end(),x);// 这个时间复杂度为O(n*logn*logn)
代码即是对操作的模拟。
code:
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define ios std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define int long long
#define x first
#define y second
typedef pair<int,int> pii;
//head
const int N=1e3+10,mod=998244353;
int n;
multiset<int> s;
void work()
{
int q;
cin>>q;
while(q--){
int op,x,k;
cin>>op>>x;
if(op==1){
s.insert(x);
}
else if(op==2){
cin>>k;
auto id=s.upper_bound(x);
while(id!=s.begin()&&k){
id--; k--;
}
if(!k) cout<<*id<<endl;
else cout<<-1<<endl;
}
else {
cin>>k;
auto id=s.lower_bound(x);
while(id!=s.end()&&k){
id++; k--;
}
id--;
if(!k) cout<<*(id)<<endl;
else cout<<-1<<endl;
}
}
}
signed main()
{
int t;
//cin>>t;
t=1;
while(t--) work();
return 0;
}
题意:给定一个序列A,长度为 N N N, 将做下列操作 K K K次。
设 X X X为糖果数量(初始为0),每次操作得到 A ( X m o d N ) A_{(XmodN)} A(XmodN)个糖果。
问操作 K K K次后,得到的糖果总数量为多少。
其中 1 ≤ K ≤ 1 0 12 1\leq K \leq 10^{12} 1≤K≤1012.
K很大,暴力做肯定是不行的,因此需要发掘一点性质,由于每次操作都会拿取下标为 X m o d N XmodN XmodN的A,根据抽屉原理,可知最多操作 N + 1 N+1 N+1次,一定会出现重复拿取同一个下标的A。那么这有什么性质呢?假设第二次拿取了 A k A_k Ak,那么接下来拿的顺序我们就可以知道了:即是重复之前的操作,把之前的顺序再重复一遍,也就是会形成一个循环节。
因此只需判断什么时候会形成循环节,然后根据前缀和来计算这一段的总和,再算出循环的次数,就很容易能算出答案。
code:
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define ios std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define int long long
#define x first
#define y second
typedef pair<int,int> pii;
//head
const int N=5e5+10,mod=998244353;
int n,k;
int a[N],s[N];
void work()
{
cin>>n>>k;
for(int i=0;i<n;i++) {
cin>>a[i];
}
int l,r;
map<int, int> mp;
for(int i=1;i<=n+1;i++){
s[i]=s[i-1]+a[s[i-1]%n];
if(mp[s[i]%n]){
l=mp[s[i]%n]+1;
r=i;
break;
}
mp[s[i]%n]=i;
}
int ans=0;
if(k<=r) {
ans=s[k];
}
else {
//cout<<l<<endl;
k-=(l-1);
ans+=s[l-1];
int cnt=k/(r-l+1);
ans+=cnt*(s[r]-s[l-1]);
int m=k%(r-l+1);
ans+=s[m+l-1]-s[l-1];
}
cout<<ans<<endl;
}
signed main()
{
int t;
//cin>>t;
t=1;
while(t--) work();
return 0;
}
题意:由个 N ∗ M N*M N∗M的网格,给定起点和终点,同时给出K个障碍物的坐标,问:
是否能从起点到终点,若可以,求出最短的步数。
移动规则为,可以朝上下左右四个方向移动,只有遇到障碍物会停下,否则会滑出网格外,视为无法到达。
只有正好停在终点才算到达终点。
记得之前有场ABC的一题和这一题巨像,那一题是根据指令判断能否到达终点。
注意到要求最短步数,可以想到使用BFS,但是由于N,M比较大,所以不能使用普通的走法,可以用二分来查找障碍物的坐标,然后就是模拟部分了,为了防止判断一些边界情况,插入了两个哨兵,当然不插入也可以。
实际上这题不难,只是我写的代码略微有点丑陋,也有很多其他做法。
code:
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define ios std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define int long long
#define x first
#define y second
typedef pair<int,int> pii;
//head
const int N=1e5+10;
struct node{
pii p;
int d;
};
int n,m,q;
int sx,sy,ex,ey;
map<int,set<int>> r,c;
map<pii, int> st;
int ans;
int bfs()
{
queue<node> q;
q.push({{sx,sy},0});
while(q.size())
{
auto t=q.front().p;
int w=q.front().d;
q.pop();
if(st[{t.x,t.y}]) continue;
st[{t.x,t.y}]=1;
//cout<<"----"<<t.x<<" "<<t.y<<" "<<w<<"---"<<endl;
if(t.x==ex&&t.y==ey) return w;
int x=t.x,y=t.y;
int a,b;
c[y].insert(-1e18);
c[y].insert(1e18);
auto id=c[y].lower_bound(x); id--;
a=*id+1,b=y;
if(a!=x&&b==y&&a>0&&a<=n) {
q.push({{a,b},w+1});//cout<<w+1<<a<<"##"<<b<<endl;
//if(a==ex&&b==ey) return w+1;
}
r[x].insert(-1e18);
r[x].insert(1e18);
id=r[x].upper_bound(y);
b=*id-1,a=x;
if(a==x&&b!=y&&b>0&&b<=m) {
q.push({{a,b},w+1});//cout<<w+1<<a<<"##"<<b<<endl;
//if(a==ex&&b==ey) return w+1;
}
c[y].insert(-1e18);
c[y].insert(1e18);
id=c[y].upper_bound(x);
a=*id-1,b=y;
if(a!=x&&b==y&&a>0&&a<=n) {
q.push({{a,b},w+1});//cout<<w+1<<a<<"##"<<b<<endl;
//if(a==ex&&b==ey) return w+1;
}
r[x].insert(-1e18);
r[x].insert(1e18);
id=r[x].lower_bound(y); id--;
b=*id+1,a=x;
if(a==x&&b!=y&&b>0&&b<=m) {
q.push({{a,b},w+1});//cout<<w+1<<a<<"##"<<b<<endl;
//if(a==ex&&b==ey) return w+1;
}
}
return -1;
}
void work()
{
cin>>n>>m>>q;
cin>>sx>>sy>>ex>>ey;
for(int i=1;i<=q;i++){
int x,y; cin>>x>>y;
r[x].insert(y);
// r[x].insert(-1e18);
// r[x].insert(1e18);
c[y].insert(x);
// c[y].insert(-1e18);
// c[y].insert(1e18);
}
int ans=bfs();
cout<<ans<<endl;
}
signed main()
{
ios;
int t;
t=1;
while(t--) work();
return 0;
}