A 海港
输出
输出n行,第i行输出一个整数表示第i艘船到达后的统计信息。
样例输入
3
1 4 4 1 2 2
2 2 2 3
10 1 3
样例输出
3
4
4
提示
【样例解释1】
第一艘船在第1秒到达海港,最近24小时到达的船是第一艘船,共有4个乘客, 分别是来自国家4,1,2,2共来自3个不同的国家;
第二艘船在第2秒到达海港,最近24小时到达的船是第一艘船和第二艘船,共有4 + 2 =6个乘客,分别是来自国家4,1,2,2,2,3共来自4个不同的国家;
第三艘船在第10秒到达海港,最近24小时到达的船是第一艘船、第二艘船和第 三艘船,共有4+ 2+1=7个乘客,分别是来自国家4,1,2,3共来自4个不同 的国家。
因为这个题只记录在一艘船到达的时间前24小时内的人的国籍,这样有来的也有走的,先到的先走,所以是不是想到了一个数据结构呢?没错,用队列来模拟就好了,但是如果每一秒每一秒的来存,那么需要10^9的数组,很显然是不行的,这时候看到人的总和只有3×10^5,那么就按人来存好了,这样只需要3×10^5的数组,还要注意在24小时前的船只也要走,也就是不包括正好24小时前的。
#include<bits/stdc++.h>
#define exp 1e-8
#define mian main
#define pii pair<int,int>
#define pll pair<ll,ll>
#define ll long long
#define pb push_back
#define PI acos(-1.0)
#define inf 0x3f3f3f3f
#define w(x) while(x--)
#define int_max 2147483647
#define lowbit(x) (x)&(-x)
#define gcd(a,b) __gcd(a,b)
#define pq(x) priority_queue<x>
#define ull unsigned long long
#define scn(x) scanf("%d",&x)
#define scl(x) scanf("%lld",&x)
#define pl(a,n) next_permutation(a,a+n)
#define ios ios::sync_with_stdio(false)
#define met(a,x) memset((a),(x),sizeof((a)))
using namespace std;
const int N=3e5+10;
int n;
struct node
{
int time;
int p;
};
int gj[N];
queue<node>q;
int main()
{
while(~scanf("%d",&n)){
int ans=0;
met(gj,0);
int t,c;
node m;
for(int i=1;i<=n;i++){
scanf("%d%d",&t,&c);
for(int j=1;j<=c;j++){
m.time=t;
scanf("%d",&m.p);
if(!gj[m.p])
ans++;
gj[m.p]++;
q.push(m);
}
while(1){
node mm=q.front();
if(mm.time+86400>m.time)
break;
gj[mm.p]--;
if(gj[mm.p]==0)
ans--;
q.pop();
}
printf("%d\n",ans);
}
}
}
D 回文日期
题目描述
在日常生活中,通过年、月、日这三个要素可以表示出一个唯一确定的日期。
牛牛习惯用8位数字表示一个日期,其中,前4位代表年份,接下来2位代表月 份,最后2位代表日期。显然:一个日期只有一种表示方法,而两个不同的日期的表 示方法不会相同。
牛牛认为,一个日期是回文的,当且仅当表示这个日期的8位数字是回文的。现 在,牛牛想知道:在他指定的两个日期之间包含这两个日期本身),有多少个真实存 在的日期是回文的。
一个8位数字是回文的,当且仅当对于所有的i(1<= i <= 8)从左向右数的第i个 数字和第9-i个数字(即从右向左数的第i个数字)是相同的。
例如:
•对于2016年11月19日,用8位数字20161119表示,它不是回文的。
•对于2010年1月2日,用8位数字20100102表示,它是回文的。
•对于2010年10月2日,用8位数字20101002表示,它不是回文的。
每一年中都有1212个月份:
其中,1,3,5,7,8,10,121,3,5,7,8,10,12月每个月有31天;4,6,9,114,6,9,11月每个月有30天;而对于22月,闰年时有29天,平年时有28天。
一个年份是闰年当且仅当它满足下列两种情况其中的一种:
1.这个年份是4的整数倍,但不是100的整数倍;
2.这个年份是400的整数倍。
例如:
•以下几个年份都是闰年:2000,2012,20162000,2012,2016。
•以下几个年份是平年:1900,2011,20141900,2011,2014。
输入
两行,每行包括一个8位数字。
第一行表示牛牛指定的起始日期。
第二行表示牛牛指定的终止日期。
保证date_i和都是真实存在的日期,且年份部分一定为4位数字,且首位数字不为0。
保证date 1 —定不晚于date 2。
输出
一个整数,表示在date1和date2之间,有多少个日期是回文的。
样例输入
20110101
20111231
样例输出
1
提示
样例说明】
对于样例1,符合条件的日期是20111102。
对于样例2,符合条件的日期是20011002和20100102。
【子任务】
对于%60的数据,满足date1 = date2
这个题目直接模拟就好了,可能有一些麻烦,首先需要一个函数判断一下当前年份是否为闰年,还需要判断是否到达终止日期,
另外在就是判断回文了,并且我们可以看出每一年只可能有一个回文日期,所以当有一年有回文日期后,直接进入下一年即可
#include<bits/stdc++.h>
#define exp 1e-8
#define mian main
#define pii pair<int,int>
#define pll pair<ll,ll>
#define ll long long
#define pb push_back
#define PI acos(-1.0)
#define inf 0x3f3f3f3f
#define w(x) while(x--)
#define int_max 2147483647
#define lowbit(x) (x)&(-x)
#define gcd(a,b) __gcd(a,b)
#define pq(x) priority_queue<x>
#define ull unsigned long long
#define sc(x) scanf("%d",&x)
#define scl(x) scanf("%lld",&x)
#define pl(a,n) next_permutation(a,a+n)
#define ios ios::sync_with_stdio(false)
#define met(a,x) memset((a),(x),sizeof((a)))
using namespace std;
int x,y,yy,y2,m1,m2,d1,d2;
int day[13]={0,31,28,31,30,31,30,31,31,30,31,30,31}; //这里二月的天数写28,29都行,到时需要特判
int rn(int x)
{
return ((x%4==0&&x%100!=0)||x%400==0)?29:28;
}
bool check()
{
return (yy<y2||(yy==y2&&m1<m2)||(yy==y2&&m1==m2&&d1<=d2));
}
bool cz(int y,int m,int d)
{
int s[8];
int p=y*10000+m*100+d;
for(int i=0;i<8;i++){
s[i]=p%10;
p/=10;
}
for(int i=0;i<4;i++)
if(s[i]!=s[7-i])
return false;
return true;
}
int main()
{
while(~scanf("%d%d",&x,&y)){
int ans=0;
yy=x/10000;y2=y/10000; //年
m1=(x/100)%100;m2=(y/100)%100; //月
d1=x%100;d2=y%100; //日
while(check()){
bool falg=true;
if(cz(yy,m1,d1)){
ans++;
yy++;
m1=1;
d1=1;
continue;
}
if((m1==2&&d1==rn(yy))||m1!=2&&d1==day[m1]){
m1++;
d1=1;
falg=false;
}
if(m1==13){
yy++;
m1=1;
d1=1;
falg=false;
}
if(falg)
d1++;
}
printf("%d\n",ans);
}
}
E 求和
数学公式略微麻烦
F 推销员
题目描述
阿明是一名推销员,他奉命到螺丝街推销他们公司的产品。螺丝街是一条死胡同,出口 与入口是同一个,街道的一侧是围墙,另一侧是住户。螺丝街一共有 N 家住户,第 i 家住户 到入口的距离为 Si 米。由于同一栋房子里可以有多家住户,所以可能有多家住户与入口的 距离相等。阿明会从入口进入,依次向螺丝街的 X 家住户推销产品,然后再原路走出去。 阿明每走 1 米就会积累 1 点疲劳值,向第 i 家住户推销产品会积累 Ai点疲劳值。阿明 是工作狂,他想知道,对于不同的 X,在不走多余的路的前提下,他最多可以积累多少点疲 劳值.
输入
第一行有一个正整数 N,表示螺丝街住户的数量。 接下来的一行有 N 个正整数,其中第 i 个整数 Si表示第 i 家住户到入口的距离。数据保 证 S1≤S2≤…≤Sn<1e8。 接下来的一行有 N 个正整数,其中第 i 个整数 Ai表示向第 i 户住户推销产品会积累的 疲劳值。数据保证 Ai<1e3。
输出
输出 N 行,每行一个正整数,第 i 行整数表示当 X=i 时,阿明最多积累的疲劳值。
样例输入
5 1 2 3 4 5 1 2 3 4 5
样例输出
15 19 22 24 25
提示
【输入输出样例 说明】
X=1: 向住户 5 推销,往返走路的疲劳值为 5+5,推销的疲劳值为 5,总疲劳值为 15。
X=2: 向住户 4、5 推销,往返走路的疲劳值为 5+5,推销的疲劳值为 4+5,总疲劳 值为 5+5+4+5=19。
X=3: 向住户 3、4、5 推销,往返走路的疲劳值为 5+5,推销的疲劳值 3+4+5,总疲 劳值为 5+5+3+4+5=22。
X=4: 向住户 2、3、4、5 推销,往返走路的疲劳值为 5+5,推销的疲劳值 2+3+4+5, 总疲劳值 5+5+2+3+4+5=24。
X=5: 向住户 1、 2、 3、 4、 5 推销,往返走路的疲劳值为 5+5,推销的疲劳值 1+2+3+4+5, 总疲劳值 5+5+1+2+3+4+5=25。
一道贪心的题目,每一次都是在上一次的情况下进行更新,一开始的思路是先找到从起点开始到那n个点中总疲劳值最大的,在分别看往左走和往右走哪个疲劳度消耗的更多,注意在这种情况下:
向左走只需要加上推销的疲劳值,因为他已经走过这里了,就等于顺路推销
向右走的话需要 当前点的距离减去他之前的点的距离×2+推销当前的花费,也就是(a[i].dis-a[now].dis)*2+a[i].w。在更新一下now,就是那个当前最远到达的点。
当向左走和向右走花费一样的时候,无所谓哪个了,都可以的。
把向左走和向右走的比较一下就好了,但是不知道什么原因在洛谷只过了30......orz
然后想到向左走的的用大根堆优化一下(优先队列),,只需要计算向右走的就好了。
具体看代码。。。
#include<bits/stdc++.h>
#define exp 1e-8
#define mian main
#define pii pair<int,int>
#define pll pair<ll,ll>
#define ll long long
#define pb push_back
#define PI acos(-1.0)
#define inf 0x3f3f3f3f
#define w(x) while(x--)
#define int_max 2147483647
#define lowbit(x) (x)&(-x)
#define gcd(a,b) __gcd(a,b)
#define pq(x) priority_queue<x>
#define ull unsigned long long
#define sc(x) scanf("%d",&x)
#define scl(x) scanf("%lld",&x)
#define pl(a,n) next_permutation(a,a+n)
#define ios ios::sync_with_stdio(false)
#define met(a,x) memset((a),(x),sizeof((a)))
using namespace std;
const int N=1e5+10;
int n;
priority_queue<int>q;
struct node
{
int dis;
int w;
}a[N];
int main()
{
while(~scanf("%d",&n)){
for(int i=1;i<=n;i++)
sc(a[i].dis);
for(int i=1;i<=n;i++)
sc(a[i].w);
int now=0;
q.push(0);
int ans=0;
for(int i=1;i<=n;i++){
int p=q.top();
int pp=now;
int maxn=0;
for(int i=now+1;i<=n;i++)
if((a[i].dis-a[now].dis)*2+a[i].w>maxn){
pp=i;
maxn=(a[i].dis-a[now].dis)*2+a[i].w;
}
if(maxn>p){ //比较是否向右走比向左走花费高
q.push(maxn); //高就讲右边的入队
for(int i=now+1;i<pp;i++)
q.push(a[i].w);
now=pp;
}
ans+=q.top(); //更新答案
q.pop();
printf("%d\n",ans);
}
}
}
/*
5
1 2 2 4 5
5 4 3 4 1
*/