标题:日志统计
小明维护着一个程序员论坛。现在他收集了一份"点赞"日志,日志共有N行。其中每一行的格式是:
ts id
表示在ts时刻编号id的帖子收到一个"赞"。
现在小明想统计有哪些帖子曾经是"热帖"。如果一个帖子曾在任意一个长度为D的时间段内收到不少于K个赞,小明就认为这个帖子曾是"热帖"。
具体来说,如果存在某个时刻T满足该帖在[T, T+D)这段时间内(注意是左闭右开区间)收到不少于K个赞,该帖就曾是"热帖"。
给定日志,请你帮助小明统计出所有曾是"热帖"的帖子编号。
【输入格式】
第一行包含三个整数N、D和K。
以下N行每行一条日志,包含两个整数ts和id。
对于50%的数据,1 <= K <= N <= 1000
对于100%的数据,1 <= K <= N <= 100000 0 <= ts <= 100000 0 <= id <= 100000
【输出格式】
按从小到大的顺序输出热帖id。每个id一行。
【输入样例】
7 10 2
0 1
0 10
10 10
10 1
9 1
100 3
100 3
【输出样例】
1
3
这个题要用到尺取法。
关于“尺取法”,我的理解:
(1)涉及“(寻找任一个)区间”。
(2)想清楚两个点:①针对题意,怎么找到这个区间,即这个区间应满足怎样的条件。②关于start和end标识,什么时候start++,什么时候end++,什么时候应该跳出循环。anyway,要好好分析题意,结合题意设计。
#include<iostream> #include<bits/stdc++.h> using namespace std; int n,d,k; vector<int>v[100005]; set<int>ans; bool judge(int id) { int cnt=0; int len=v[id].size(); if(len<k) return 0; int start=0,end=0; sort(v[id].begin(),v[id].end()); while(start<=end&&end<len) { cnt++; if(cnt>=k) { if(v[id][end]-v[id][start]<d) { return 1; } else { cnt--; start++; } } end++; } return 0; } int main() { int ts,id; cin>>n>>d>>k; while(n--) { cin>>ts>>id; v[id].push_back(ts); } for(int i=1;i<=1010;i++) { if(judge(i)) { ans.insert(i); } } set<int>::iterator it; for(it=ans.begin();it!=ans.end();it++) { cout<<*it<<endl; } return 0; }
标题:全球变暖
你有一张某海域NxN像素的照片,"."表示海洋、"#"表示陆地,如下所示:
.......
.##....
.##....
....##.
..####.
...###.
.......
其中"上下左右"四个方向上连在一起的一片陆地组成一座岛屿。例如上图就有2座岛屿。
由于全球变暖导致了海面上升,科学家预测未来几十年,岛屿边缘一个像素的范围会被海水淹没。具体来说如果一块陆地像素与海洋相邻(上下左右四个相邻像素中有海洋),它就会被淹没。
例如上图中的海域未来会变成如下样子:
.......
.......
.......
.......
....#..
.......
.......
请你计算:依照科学家的预测,照片中有多少岛屿会被完全淹没。
【输入格式】
第一行包含一个整数N。 (1 <= N <= 1000)
以下N行N列代表一张海域照片。
照片保证第1行、第1列、第N行、第N列的像素都是海洋。
【输出格式】
一个整数表示答案。
【输入样例】
7
.......
.##....
.##....
....##.
..####.
...###.
.......
【输出样例】
1
一个dfs判断
#include<iostream> #include<cstdio> using namespace std; int mp[110][110]; int ans[11000]; bool vis[110][110]; void dfs(int x,int y,int k) { if(mp[x][y]=='.') return; if(vis[x][y]) return; vis[x][y]=1; if(mp[x-1][y]=='#'&&mp[x+1][y]=='#'&&mp[x][y-1]=='#'&&mp[x][y+1]=='#') ans[k]++; dfs(x+1,y,k); dfs(x-1,y,k); dfs(x,y-1,k); dfs(x,y+1,k); } int main() { int n; scanf("%d",&n); for(int i=1;i<=n;i++) { getchar(); for(int j=1;j<=n;j++) scanf("%c",&mp[i][j]); } int len=0; for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { if(mp[i][j]=='#'&&!vis[i][j]) { dfs(i,j,len); len++; } } } int sum=0; for(int i=0;i<len;i++) if(ans[i]==0) sum++; printf("%d ",sum); }
本题给定一个庞大家族的家谱,要请你给出最小一辈的名单。
输入格式:
输入在第一行给出家族人口总数 N(不超过 100 000 的正整数) —— 简单起见,我们把家族成员从 1 到 N 编号。随后第二行给出 N 个编号,其中第 i 个编号对应第 i 位成员的父/母。家谱中辈分最高的老祖宗对应的父/母编号为 -1。一行中的数字间以空格分隔。
输出格式:
首先输出最小的辈分(老祖宗的辈分为 1,以下逐级递增)。然后在第二行按递增顺序输出辈分最小的成员的编号。编号间以一个空格分隔,行首尾不得有多余空格。
输入样例:
9
2 6 5 5 -1 5 6 4 7
输出样例:
4
1 9
用到了树和递归思想
#include<iostream> #include<cstdio> #include<string.h> #include<math.h> #include<algorithm> using namespace std; int f[1000001],a[1000001]; int find(int x) { if(a[x]) return a[x]; else if(f[x]==-1) return a[x]=1; else return a[x]=find(f[x])+1; } int main() { int n,i; cin>>n; for(i=1;i<=n;i++) { cin>>f[i]; } int max=0; for(i=1;i<=n;i++) { if(find(i)>max) max=find(i); } cout<<max<<endl; int flag=1; for(i=1;i<=n;i++) { if(a[i]==max) { if(flag==0) cout<<" "; cout<<i; flag=0; } } return 0; }