第二次训练

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
*/

猜你喜欢

转载自blog.csdn.net/curry___/article/details/83446282