链接 链接
#include
#include
#include
#include
using namespace std;
const int N = 100010; //根据题目数据范围,定N大小,此题则主要根据N,ts,id来确定的
typedef pair<int, int> PII; //定义一个PII类型以及一对int整型用于存储ts和id
#define x first //为了代码简洁,则分别把first, second 宏定义为x, y
#define y second
int n, d, k;
int cnt[N]; //用于存储每个id号获得赞数,所以后面代码为cnt[t] ++;
bool st[N]; //用于存储每个帖子是否是热帖,所以用bool类型
PII logs[N];//用于存储日志ts, id
int main()
{
scanf("%d %d %d", &n, &d, &k);
for(int i = 0; i < n; i ++) scanf("%d %d\n", &logs[i].first, &logs[i].second);
sort(logs, logs + n);
for(int i = 0, j = 0; i < n; i ++)//双指针算法,i在前,j在后
{
int t = logs[i].second;//把每个获赞的帖子id存入t
cnt[t] ++;//获得一个赞,所以此刻 ++;
while(logs[i].first - logs[j].first >= d)//如果俩个帖子时间相差超过d,说明该赞无效
{
cnt[logs[j].second] --;//所以此刻--;
j ++;//要把指针j往后,否则死循环
}
if(cnt[t] >= k) st[t] = true; //如果该id贴赞超过k,说明是热帖
}
for(int i = 0; i < 100000; i ++)
{
if(st[i])//如果为真,则把热帖的id打印出来
cout << i << endl;
}
return 0;
}
BFS 通常用于求解——》 最短路径
链接 链接
#include
#include
#include
using namespace std;
typedef pair<int, int> PII;
const int N = 210;
char a[N][N];
int dis[N][N];
void bfs(PII start) {
queue<PII> q;
q.push(start);//队头队,对应步骤1
while(!q.empty()) {
PII u = q.front();
q.pop();
int dx[4] = {-1, 0, 1, 0};
int dy[4] = {0, 1, 0 ,-1};
for(int i = 0; i < 4; i++) {//遍历四个方向,对应步骤2
int x = u.first + dx[i];
int y = u.second + dy[i];
if(a[x][y] == '#') continue;//如果是'#',不做任何处理
if(a[x][y] == '.') {//如果是 '.',更新对应内容
dis[x][y] = dis[u.first][u.second] + 1;
a[x][y] = '#';
q.push({x, y});
}
if(a[x][y] == 'E') {//如果是'E',找到了,输出
cout << dis[u.first][u.second] + 1 << endl;
return;
}
}
}
cout << "oop!" << endl;//没有找到
}
int main() {
int t;
cin >> t;
while(t--) {
memset(a, '#', sizeof(a));//初始化地图,各个点都是墙。
memset(dis, 0, sizeof(dis));//初始化dis
int n,m;
PII start;
cin >> n >> m;
for(int i = 1; i <= n; i++) {//从第一行存储地图,因为四周都是墙,bfs时,可以不做越界判断
for(int j = 1; j <= m; j++) {//从第一;列存储地图,因为四周都是墙,bfs时,可以不做越界判断
cin >> a[i][j];
if(a[i][j] == 'S')//记录下起点位置。
start.first = i, start.second = j, a[i][j] = '#';
}
}
bfs(start);
}
return 0;
}
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int, int> PII;
#define rep(i, a, n) for(int i = a; i <= n; i ++)
#define per(i, a, n) for(int i = n; i <= a; i --)
#define pb push_back
#include // atoi
#define debug cout<<"debug"<<"\n"
#define endl "\n";
const int INF = 0x3f3f3f3f;
const int mod=1e9+7;
const int N = 30;
#define x first
#define y second
char g[N][N];
int cnt[N][N];
int dx[4] = {0, 1, 0, -1};
int dy[4] = {1, 0, -1, 0};
int bfs (PII s) {
int res = 1;
queue<PII> q;
q.push(s);
while(!q.empty()) {
auto t = q.front();
q.pop();
for(int i = 0; i < 4; i ++) {
int xx = dx[i] + t.x , yy = dy[i] + t.y;
if(g[xx][yy] == '#') continue;
if(g[xx][yy] == '.') {
// cnt[xx][yy] = cnt[t.x][t.y] + 1;
g[xx][yy] = '#';
q.push({xx, yy});
res ++ ;
}
}
}
return res;
}
void solve () {
int n, m;
while(cin >> n >> m) {
if(n == 0 && m == 0) break;
memset(g, '#', sizeof g);
// memset(cnt , 0, sizeof cnt);
PII s;
rep(i , 1, m) {
rep(j , 1, n) {
cin >> g[i][j];
if(g[i][j] == '@') {
s.x = i;
s.y = j;
g[i][j] = '#';
}
}
}
cout << bfs(s) <<endl;
}
}
int main(void){
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int T = 1;
// cin >> T;
while(T --) solve();
return 0;
}
链接 链接
一个数据结构题 : 完全二叉树的最右边的节点为 2 * i - 1
最左的节点为 2depth
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int, int> PII;
#define rep(i, a, n) for(int i = a; i <= n; i ++)
#define per(i, a, n) for(int i = n; i <= a; i --)
#define pb push_back
#include // atoi
#define debug cout<<"debug"<<"\n"
#define endl "\n"
const int INF = 0x3f3f3f3f;
const int mod=1e9+7;
const int N = 30;
#define x first
#define y second
int a[N];
int cnt[N];
ll minn = INF;
ll maxx = -INF;
void solve () {
int n;
rep(i , 1 , n) cin >> a[i];
int depth = 0;
for(int d = 1, i = 1; i <= n; i *= 2, d ++) {
ll s = 0;
for(int j = i; j < i + (1 << d - 1) && j <= n; j ++) {
s += a[i];
}
if(s > maxx) {
maxx = s;
depth = d;
}
}
cout << depth << endl;
// for(int i = 1; i < n ; i+)
}
int main(void){
// freopen("in.txt","r",stdin);
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int T = 1;
// cin >> T;
while(T --) solve();
return 0;
}
链接 链接
思路 : 三维坐标, 用结构体存储 , queue
用不了 可以模拟队列 hh
头指针 tt
尾指针 https://www.acwing.com/video/257/
**判断 越界就 continue
能走 就 dis + 1
题目链接
左孩子右兄弟表示法是一种将树转化成一颗二叉树的方法;
该方法将某节点的所有兄弟节点都定位该节点的右孩子, 将该节点的任意一个孩子定位左孩子;
题目要求能够造出二叉树的最大深度;
经过观察可得, 某一层节点能够形成的深度其实就是该节点的兄弟的数量;
因此要使树的深度最深, 则树的向下构造节点的孩子数量要尽量多;
状态表示f[i] : 表示i节点作为根节点能够形成二叉树的高度;
对哪一个节点向下构造做分类: f[i] = max(f[j]) + cnt;
(cnt为i节点的孩子数量)
初始化:无;
答案: f[1];
#include
#include
#include
const int N = 1e5 + 10;
using namespace std;
int n;
int h[N], ne[N], e[N], idx = 0;
int f[N];
void add(int a, int b){
e[idx] = b, ne[idx] = h[a], h[a] = idx ++;
}
void dfs(int x) {
int cnt = 0;
for(int i = h[x]; i != -1; i = ne[i]) {
int j = e[i];
dfs(j);
cnt ++;
f[x] = max(f[x], f[j]);
}
f[x] += cnt;
}
void solve () {
cin >> n;
memset(h, -1 , sizeof h);
for(int i = 2; i <= n; i ++) {
int v;
cin >> v;
add(v, i);
}
dfs(1);
cout << f[1] << endl;
}
int main(void){
// freopen("in.txt","r",stdin);
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int T = 1;
// cin >> T;
while(T --) solve();
return 0;
}
题目链接
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int, int> PII;
#define rep(i, a, n) for(int i = a; i <= n; i ++)
#define per(i, a, n) for(int i = n; i <= a; i --)
#define pb push_back
#include // atoi
#define debug cout<<"debug"<<"\n"
#define endl "\n"
const int INF = 0x3f3f3f3f;
const int mod=1e9+7;
const int N = 110;
const int M = N * 2;
#define x first
#define y second
int dx[8] = {-2, -1, 1, 2, 2, 1, -1, -2};
int dy[8] = {1, 2, 2, 1, -1, -2, -2, -1};
int cnt [N][N];
int res = 0;
int n, m , k;
void dfs(int x, int y, int sum) {
if(sum == k) {
res = (res + 1) % mod;
return ;
}
if(y > m) {
y = 1, x ++;
if(x > n) return ;
}
dfs(x, y + 1, sum); // 不放马
if(!cnt[x][y]) {
cnt[x][y] ++;
for(int i = 0; i < 8; i ++) {
int a = x + dx[i], b = y + dy[i];
if(a < 1 || a > n || b < 1 || b > m) continue;
cnt[a][b]++;
}
dfs(x, y + 1, sum);
cnt[x][y] --;
for(int i = 0; i < 8; i ++) {
int a = x + dx[i], b = y + dy[i];
if(a < 1 || a > n || b < 1 || b > m) continue;
cnt[a][b] --;
}
// cnt[x][y] --;
}
}
void solve () {
cin >> n >> m >> k;
dfs(1, 1, 0);
cout << res << endl;
}
int main(void){
// freopen("in.txt","r",stdin);
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int T = 1;
// cin >> T;
while(T --) solve();
return 0;
}
题目 链接
双指针
算法#include
#include
#include
using namespace std;
#include
#include
#include
using namespace std;
int main ( ) {
int n;
string s;
cin >>n >>s;
int ans = 0;
for (int i = 0; i < n; i ++ ) {
if(s[i] != 'x') continue;
int j = i + 1;
while(j < n && s[j] == 'x') j ++;
ans += max(0, j - i - 2);
i = j - 1;
}
cout << ans << endl;
return 0;
}
int main ( ) {
int n;
string s;
cin >>n >>s;
int ans = 0;
for (int i = 0; i < n; i ++ ) {
if(s[i] != 'x') continue;
int j = i + 1;
while(j < n && s[j] == 'x') j ++;
ans += max(0, j - i - 2);
i = j - 1;
}
cout << ans << endl;
return 0;
}
双指针
模板题+1
res
加上 i - j + 1
即可#include
using namespace std;
const int N = 100010;
int a[N], cnt[N];
int n, ans;
int main() {
scanf("%d", &n);
for (int i = 0; i < n; i++) {
scanf("%d", &a[i]);
}
for (int i = 0, j = 0; j < n; j++) {
cnt[a[j]] ++;
while (cnt[a[j]] > 1) {
cnt[a[i]] --;
i++;
}
ans = max(ans, j - i + 1);
}
printf("%d", ans);
return 0;
}
题目 链接
#include
using namespace std;
typedef long long LL;
char c[20];
LL ans=0;
//n:1号操作剩余次数 m:2号操作剩余次数
int n,m;
void dfs(int i,LL v){
int x=c[i]-'0';
if(c[i]){
//应该使用的操作次数
int t = min(n,9-x);
n-=t;
dfs(i+1,v*10+x+t);
//回溯
n+=t;
//考虑操作2是否能够使用
if(m>x){
m-=x+1;
dfs(i+1,v*10+9);
//回溯
m+=x+1;
}
}else{
//答案取max
ans=max(ans,v);
}
}
int main()
{
scanf("%s%d%d",c,&n,&m);
dfs(0,0);
printf("%lld\n",ans);
return 0;
}
题目 链接
m
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int, int> PII;
#define rep(i, a, n) for(int i = a; i <= n; i ++)
#define per(i, a, n) for(int i = n; i <= a; i --)
#define pb push_back
#include // atoi
#define debug cout<<"debug"<<"\n"
#define endl "\n"
const int INF = 0x3f3f3f3f;
const int mod=1e9+7;
const int N = 100010;
const int M = N * 2;
#define x first
#define y second
// 对于一个叶子节点,如果从该节点到根节点的路径(包括两端节点)中有超过 m
// 个黑色节点连续的排列在一起,则称该节点为无效叶子节点。
int n,m, w[N], res;
int e[M], h[N], ne[M], idx;
bool vaild, st[N];
void add (int a, int b) {
e[idx] = b,ne[idx] = h[a], h[a] = idx ++;
}
//a当前节点 fa父节点 cnt统计非法节点 叶子节点是否为非法节点
int dfs(int u, int fa, int cnt, bool vaild) {
if(w[u]) cnt ++ ; // 如果当前节点是黑节点
else cnt ++;
if(cnt > m ) vaild = false;
int res = 0, sons = 0;
for(int i = h[u]; i != -1; i = ne[i]) {
int j = e[i];
if(j == fa) continue;
sons ++;
res += dfs(j, u, cnt , vaild); // 递归下一个节点
}
if(!sons && vaild) res ++; // 非法节点且字节点为叶子节点
return res;
}
void solve () {
cin >> n >> m;
memset(h, -1 , sizeof h);
for(int i = 1; i <= n; i ++) cin >> w[i];
for(int i = 0; i < n - 1; i ++) {
int a ,b;
cin >> a >> b;
add(a, b), add(b, a);
}
cout << dfs(1, -1 , 0, true) << endl;
}
int main(void){
// freopen("in.txt","r",stdin);
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int T = 1;
// cin >> T;
while(T --) solve();
return 0;
}