思路:如果能整除就直接输出a/b,否则就需要再攻击一下才能打到0
#include
#pragma GCC optimize(3,"Ofast","inline")
#pragma GCC optimize(2)
using namespace std;
typedef long long LL;
#define int LL
typedef pair<int, int> PII;
void solve()
{
int a, b;
cin >> a >> b;
if(a%b==0){
cout << a / b << endl;
}else{
cout << a/b+1 << endl;
}
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);cout.tie(nullptr);
int t = 1;
// cin >> t;
while(t -- ) solve();
system("pause");
return 0;
}
思路:深搜题。要保证snuke在一条线上,那方向不能改变,每找到一个s从它八个方向都看一下可不可以,当我path路径上放满五个PII的时候,就说明找到了答案,直接打印。
#include
#pragma GCC optimize(3,"Ofast","inline")
#pragma GCC optimize(2)
using namespace std;
typedef long long LL;
#define int LL
typedef pair<int, int> PII;
const int N = 110;
int dx[8] = {0,-1,0,1,1,1,-1,-1},dy[8]={1,0,-1,0,1,-1,1,-1};
char a[N][N];
int h, w;
PII path[6];
string str="snuke";
void dfs(int x, int y, int f,int cnt)//f为方向,方向每次不能改变
{
path[cnt] = {x, y};
if(cnt == 4){
for(int i = 0; i < 5; i ++ ){
cout << path[i].first << ' ' << path[i].second << endl;
}
return;
}
int xx = x + dx[f], yy = y + dy[f];
if(xx<1||yy<1||xx>h||yy>w) return;
if(str[cnt+1] == a[xx][yy]){
dfs(xx,yy,f,cnt+1);
}
}
void solve()
{
cin >> h >> w;
for(int i = 1; i <= h; i ++ ){
for(int j = 1; j <= w; j ++ ){
cin >> a[i][j];
}
}
for(int i = 1; i <= h; i ++ ){
for(int j = 1; j <= w; j ++ ){
if(a[i][j] == 's'){//第一个字母是s就搜
for(int k = 0; k < 8; k ++ ){
int x = i + dx[k],y=j+dy[k];
if(x<1||y<1||x>h||y>w){
continue;
}
dfs(i,j,k,0);
}
}
}
}
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);cout.tie(nullptr);
int t = 1;
// cin >> t;
while(t -- ) solve();
system("pause");
return 0;
}
思路:还是深搜题,看这个n,m那么少,那么一定最暴力的算法就可以了。用字符串数组存,从1到n遍历,如果一个字符串没有用过并且符合条件(与当前字符串有且仅有一个字母不同),那就以这个新的字符串为起始点,标记用过,继续搜。
#include
#pragma GCC optimize(3,"Ofast","inline")
#pragma GCC optimize(2)
using namespace std;
typedef long long LL;
#define int LL
typedef pair<int, int> PII;
const int N = 10;
string s[N];
bool st[N];
int n, m;
int flag;
bool check(string a, string b){
int cnt = 0;
for(int i = 0; i < m; i ++ ){
if(a[i] != b[i]){
cnt ++;
if(cnt > 1) return false;
}
}
if(cnt == 1) return true;
return false;
}
void dfs(int x,int cnt)//当前枚举的哪个字符串,枚举几个了
{
if(cnt == n - 1){
cout << "Yes" << endl;
flag = 1;
return;
}
for(int i = 0; i < n; i ++ ){
if(check(s[i],s[x]) && !st[i]){
st[i] = 1;
dfs(x+1,cnt+1);
st[i] = 0;
}
if(flag) return;
}
}
void solve()
{
cin >> n >> m;
for(int i = 0; i < n; i ++ )
cin >> s[i];
sort(s,s+n);
for(int i = 0; i < n; i ++ ){
memset(st, 0,sizeof st);
st[i] = 1;
dfs(i,0);
if(flag) break;
}
if(!flag) cout << "No" << endl;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);cout.tie(nullptr);
int t = 1;
// cin >> t;
while(t -- ) solve();
system("pause");
return 0;
}
思路:非常典型的二分题。由于我基本功不扎实调了半天 排一遍b数组,对于a里的每个数我都二分去b里面找符合条件(abs(b[mid]-x)<=d)的最大值,然后对于每个ai找到的结果取max
#include
#pragma GCC optimize(3,"Ofast","inline")
#pragma GCC optimize(2)
using namespace std;
typedef long long LL;
#define int LL
typedef pair<int, int> PII;
const int N = 200010;
int a[N], b[N];
int n, m, d;
int res = -1;
void solve()
{
cin >> n >> m >> d;
int l, r, mid;
for(int i = 0; i < n; i ++ ) cin >> a[i];
for(int i = 0; i < m; i ++ ) cin >> b[i];
sort(b, b + m);
for(int i = 0; i < n; i ++ ){
//abs(x-b[mid])<=d有两种可能
//x大或者小,一起写的话不太好分,我就分成两种情况了
int x = a[i];
l = 0, r = m - 1;
//先假设a大于b
while(l < r){
mid = l + r >> 1;
if(x - b[mid] <= d){
r = mid;
}else l = mid + 1;
}
if(abs(x - b[l]) <= d){
res = max(res, x + b[l]);
}
l = 0, r = m - 1;
//然后假设b大于a的情况
while(l < r){
mid = l + r + 1 >> 1;
if(b[mid] - x <= d){
l = mid;
}else r = mid - 1;
}
if(abs(b[l] - x) <= d){
res = max(res, x + b[l]);
}
}
cout << res << endl;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);cout.tie(nullptr);
int t = 1;
// cin >> t;
while(t -- ) solve();
system("pause");
return 0;
}
都不难的,能出,都怪我前面调得太慢了比赛的时候没能出这道题
思路:这显然不能用个图去存,只需要维护当前有哪些点没有边相连。开个集合数组,s[i]存的i当前与i点邻接的点(题干说保证没有重边,那开vector也行,但是我觉得set的erase用着更简单)
#include
#pragma GCC optimize(3,"Ofast","inline")
#pragma GCC optimize(2)
using namespace std;
typedef long long LL;
#define int LL
typedef pair<int, int> PII;
const int N = 300010;
unordered_set<int> s[N];
int n, q;
void solve()
{
cin >> n >> q;
int cnt = n;
while(q -- ){
int op;
cin >> op;
if(op&1){
int a, b;
cin >> a >> b;
//如果开始这个点没有边相连,加了边就要让cnt--
//如果本来这条边就有边相连,那再加一条边cnt不变
cnt -= s[a].size() == 0;
cnt -= s[b].size() == 0;
s[a].insert(b);
s[b].insert(a);
}else{
int u;
cin >> u;
//先把与u相连的点里删掉u
//如果删完u这个点就没有边连了,那cnt++
for(auto i : s[u]){
s[i].erase(u);
cnt += s[i].size() == 0;
}
//再把u的所有点集删掉
cnt += s[u].size() != 0;
s[u].clear();
}
cout << cnt << endl;
}
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);cout.tie(nullptr);
int t = 1;
// cin >> t;
while(t -- ) solve();
system("pause");
return 0;
}
思路:有相同元素的两个集合可以才可以合并,可以抽象成图,a连着b,c连着b,那么a和c也可以相通,之后如果不能让所有点连通的,就是-1,能的话是最短路/2
#include
#pragma GCC optimize(3,"Ofast","inline")
#pragma GCC optimize(2)
using namespace std;
typedef long long LL;
#define int LL
typedef pair<int, int> PII;
const int N = 200010;
int n, m;
int dis[N*2];
queue<int> q;
void solve()
{
cin >> n >> m;
vector<vector<int>> g(n + m);
for(int i = 0; i < n; i ++ ){
int k;
cin >> k;
while(k -- ){
int a;
cin >> a;
a -- ;
//m+i里m相当于偏移量,等同于i里面存了这个点,这个点的值里面也存了有i
g[a].push_back(m + i);
g[m + i].push_back(a);
}
}
memset(dis, -1, sizeof dis);
dis[0] = 0;
q.push(0);
while(q.size()){
int x = q.front();
q.pop();
//遍历每一个跟x相邻的点
//如果某个跟x相邻的点还不可达(dis[i]==-1),那么更新它的距离为dis[x]+1
for(auto i : g[x]){
if(dis[i] == -1){
dis[i] = dis[x] + 1;
q.push(i);//之后再把这个新扩进来的点加入集合
}
}
}
cout << dis[m - 1] / 2 - 1 << endl;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);cout.tie(nullptr);
int t = 1;
// cin >> t;
while(t -- ) solve();
system("pause");
return 0;
}