2019 杭电多校第一场

D Vacation

题解:题目给出两个人要去旅行,在他们前面有n辆车,每辆车有长度以及车首部到stopline 的距离以及每辆车的最大速度,后面的车不能超过前面的车。问你他们两个的车首部到达stopline的最短时间。

思路:二分答案,求出最后一辆车停在的位置。

参考代码:

#include<bits/stdc++.h>
using namespace std;

#define mkp make_pair<int,int>
typedef long long ll;
const int maxn=2e5+10;
double eps=1e-12;
ll n;
struct Node{
    ll l,s,v;
} a[maxn];
int check(double x)
{
    double ans=a[n].s-a[n].v*x;
    for(int i=n-1;i>=0;i--)
    {
         if(a[i].s-a[i].v*x<=ans+a[i+1].l) ans+=a[i+1].l;
         else ans=a[i].s-a[i].v*x;
    }
    return ans<=eps;
}

int main()
{
    while(~scanf("%lld",&n))
    {
         for(int i=0;i<=n;i++) scanf("%lld",&a[i].l);
         for(int i=0;i<=n;i++) scanf("%lld",&a[i].s);
         for(int i=0;i<=n;i++) scanf("%lld",&a[i].v);
         double l=0,r=1e18;
         while(r-l>eps)
         {
              double mid=(l+r)/2;
              if(check(mid)) r=mid;
              else l=mid;
         }
         printf("%.10f\n",r);
    }
    return 0;
}

E Path

题解:给你n个点,m条边(有向边),每天变有一定的权值。让你求删掉一些边使得1到 n 的最短路径变大的最小代价(代价是删除的边的边权之和)。

思路:先跑一遍最短路求出1到其他点的最短距离,然后 倒着dfs 求出最短路的DAG的所有边,重新建图,跑最小割就行了。

参考代码:

#include<bits/stdc++.h>/////////
#define int long long
#define ll long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
const int MAXN = 10010;
const int INF=0x3f3f3f3f3f3f3f3fll;
struct node{
    int to;
    int val;
    int next;
}edge[MAXN*100*2],e[MAXN*200*5];
int ind,pre[MAXN],vis[MAXN],dis[MAXN],pre1[MAXN],ind1;
int now[MAXN],S,T;
int n,m;
void add1(int x,int y,int z)
{
    e[ind1].to = y;
    e[ind1].val = z;
    e[ind1].next = pre1[x];
    pre1[x] = ind1 ++;
}
void spfa()
{
    for(int i = 1; i <= n; i++){
        dis[i] = INF;
        vis[i] = 0;
    }
    vis[T] = 1;
    dis[T] = 0;
    queue<int>q;
    q.push(T);
    while(!q.empty()){
        int tp = q.front();
        q.pop();
        vis[tp] = 0;
        for(int i = pre1[tp]; i != -1; i = e[i].next){
            int t = e[i].to;
            if(dis[t] > dis[tp] + e[i].val){
                dis[t] = dis[tp] + e[i].val;
                if(!vis[t]){
                    vis[t] = 1;
                    q.push(t);
                }
            }
        }
    }
}
void add(int x,int y,int z)
{
    edge[ind].to = y;
    edge[ind].val = z;
    edge[ind].next = pre[x];
    pre[x] = ind ++;
}
void dfs1(int rt)
{
    vis[rt] = 1;
    if(rt == T)return ;
    for(int i = pre1[rt]; i != -1; i = e[i].next){
        int t = e[i].to;
        if(now[rt] + dis[t] + e[i].val == dis[S]){
            now[t] = now[rt] + e[i].val;
            add(rt,t,e[i].val);
            add(t,rt,0);
            if(!vis[t]){
                dfs1(t);
            }
        }
    }
}
int bfs()
{
    memset(vis,-1,sizeof(vis));
    queue<int>q;
    vis[S] = 0;
    q.push(S);
    while(!q.empty()){
        int tp = q.front();
        q.pop();
        for(int i = pre[tp]; i != -1; i = edge[i].next){
            int t = edge[i].to;
            if(vis[t] == -1 && edge[i].val){
                vis[t] = vis[tp] + 1;
                q.push(t);
            }
        }
    }
    if(vis[T] == -1)return 0;
    return 1;
}
int dfs(int rt,int low)
{
    int used = 0;
    if(rt == T)return low;
    for(int i = pre[rt]; i != -1 && used < low; i = edge[i].next){
        int t = edge[i].to;
        if(vis[t] == vis[rt] + 1 && edge[i].val){
            int a = dfs(t,min(low-used,edge[i].val));
            used += a;
            edge[i].val -= a;
            edge[i^1].val += a;
        }
    }
    if(used == 0)vis[rt] = -1;
    return used;
}
int x[MAXN*100],y[MAXN*100],z[MAXN*100];
void Init(int flag)
{
    ind1 = 0;
    memset(pre1,-1,sizeof(pre1));
    for(int i = 1; i <= m; i++){
        if(!flag){
            add1(y[i],x[i],z[i]);
        }
        else {
            add1(x[i],y[i],z[i]);
        }
    }
}
int32_t main()
{
    int t;
    scanf("%lld",&t);
    while(t--){
        scanf("%lld%lld",&n,&m);
        for(int i = 1; i <= m; i++){
            scanf("%lld%lld%lld",&x[i],&y[i],&z[i]);
        }
        Init(0);
        S=1,T=n;
        spfa();
        Init(1);
        ind = 0;
        memset(now,0,sizeof(now));
        memset(pre,-1,sizeof(pre));
        dfs1(S);
        int ans = 0;
        while(bfs())
        {
            while(1)
            {
                int a = dfs(S,INF);
                if(!a)break;
                ans += a;
            }
        }
        printf("%lld\n",ans);
    }
    return 0;
}

I String

题解:题目意思是给你一个长度为N的字符串,然后给你一个K,让你求满足条件的字典序最小的长度为K的子序列。

对于子序列的要求为:(Li,Ri):表示子序列中对应字符的数量应该在这个区间之间

参考代码:

#include <bits/stdc++.h>
using namespace std;
const int N=2e5+7;
char s[N],ans[N];
int k,n,cnt[N][26],l[26],r[26],used[26],last;
vector<int> vec[26];
int main()
{
    while(~scanf("%s%d",s,&k))
    {
        for(int i=0;i<=25;++i) scanf("%d%d",l+i,r+i);
        n = strlen(s);
        memset(used,0,sizeof(used));
        memset(cnt[n],0,sizeof(cnt[n]));
        for(int i=0;i<26;++i) vec[i].clear();
        for(int i=n-1;i>=0;--i)
            for(int j=0;j<=25;++j)
                cnt[i][j]=cnt[i+1][j]+(s[i]==‘a‘+j);

        for(int i=0;i<=n-1;++i) vec[s[i]-‘a‘].push_back(i);
        vector<int>::iterator head[26];
        for(int i=0;i<=25;++i) head[i]=vec[i].begin();
        last=-1;
        bool temp=true;
        for(int i=0;i<=k-1;++i)
        {
            bool f1=0;
            for(int j=0;j<=25;++j)
            {
                if(used[j]==r[j]) continue;
                while(head[j]!=vec[j].end() && (*head[j])<=last) head[j]++;
                if(head[j]==vec[j].end()) continue;
                used[j]++;//加上这个位置字符
                bool flag=1;
                int pos=(*head[j]),sum=0;
                //判断已经使用的数量加上后面的剩余的数量是否满足题意
                for(int t=0;t<=25;++t)
                {
                    if(cnt[pos+1][t]+used[t]<l[t]) flag=0;
                    sum+=max(l[t]-used[t],0);
                }
                if(sum>k-i-1) flag=0;
                sum=0;
                //最多能使用的字符数量
                for(int t=0;t<=25;++t)
                    sum+=min(cnt[pos+1][t],r[t]-used[t]);
                if(sum<k-i-1) flag=0;

                if(!flag) used[j]--;
                else
                {
                    ans[i]=‘a‘+j;
                    f1=1;
                    last=pos;
                    break;
                }
            }
            if(!f1) { puts("-1");temp=false;break;}
        }
        if(!temp) continue;
        ans[k]=‘\0‘;
        printf("%s\n",ans);
    }
    return 0;
}

后面的题解慢慢更新~

原文地址:https://www.cnblogs.com/songorz/p/11229659.html

时间: 2024-08-30 12:21:18

2019 杭电多校第一场的相关文章

2019 杭电多校 第一场

2019 Multi-University Training Contest 1 补题链接:2019 Multi-University Training Contest 1 1002 Operation (HDU-6579) 题意 给定包含 \(n\) 个数的序列,\(m\) 个询问.询问有两种操作,操作 \(0\) 表示在数组最后添加一个新元素,操作 \(1\) 表示查询区间 [l,r] 的子集的异或最大值. 询问强制在线. 题解 线性基 贪心 1004 Vacation (HDU-6581)

【2019.07.22】2019杭电多校第一场

补题地址:http://acm.hdu.edu.cn/listproblem.php?vol=56 题号:6578-6590 1001: 1002:线性基 https://blog.csdn.net/Cassie_zkq/article/details/96979461 1003: 1004: 1005:? 1006: 1007: 1008: 1009: 1010: 1011: 1012: 1013: 自闭场,但补题能学到好多算法和思维,继续加油鸭- 原文地址:https://www.cnblo

2019杭电多校第一场

所有题解都在注释里面. 1004: 1 /* 2 出题人的说法:最终通过停车线的时候,一定是一个车后面堵着剩余所有车.那么影响 3 时间的就只有最前面这辆车,所以对于每一辆车,假设是它与0车堵在一起的最靠前的一辆车. 4 那么可以计算出一个值.所有的车的计算值的最大值就是答案. 5 这个就是出题人的说法 ,时间复杂度是o(n) 6 7 我个人的理解:我们做这道题得注意到一个条件,就是对当前的车,先不要考虑后面的车. 8 只考虑它与前面的那一辆车的互相作用.考虑他们什么时候撞倒. 9 首先假设第一

2019杭电多校第一场hdu6581 Vacation

Vacation 题目传送门 解题思路 一开始的时候所有车都是是按照自己原来的速度行驶,直到有一辆车x追上前面的那辆车y,此时的变化只有,1.x的速度变为y的速度2.x后面的车追上x的时间变短.所以我们只要利用优先队列,每一次都找到会在最短的时间内追上前面那辆车的x,不断更新这个过程就好了. 以及实现中的一些细节,1.对于已经追上和被追上的两辆车,我们可以看成一辆火车,每辆车就是一节车厢,其速度就是最前面那节车厢的速度,当一辆火车追上另一辆的时候,新的火车头就是前面被追上车厢的火车头,新的火车尾

[2019杭电多校第一场][hdu6582]Path

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6582 题意:删掉边使得1到n的最短路改变,删掉边的代价为该边的边权.求最小代价. 比赛时一片浆糊,赛后听到dinic瞬间思维通透XD 大致做法就是先跑一边最短路,然后再保留所有满足dis[i]+w==dis[j]的边,在这些边上跑最小割(dinic). 代码写的异常丑陋,见谅QAQ 1 #include<iostream> 2 #include<cstdio> 3 #include&l

[2019杭电多校第一场][hdu6578]Blank

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6578 计数问题想到dp不过分吧... dp[i][j][k][w]为第1-i位置中4个数最后一次出现的位置从大到小排列后为i>=j>=k>=w,但是会MLE,所以把i滚动掉. 但是这里有限制条件,把所有限制条件按右端点用vector存一下,然后处理到第i个位置时,枚举每个状态和限制条件,如果当前状态不满足则归0. 1 #include <algorithm> 2 #include

2019杭电多校第一场 Operation HDU - 6579

题意:给出一个序列,两种操作,求区间[l,r]的区间最大异或和,和在末尾添加一个数 思路:强制在线,保存每个线性基的数值,接下去直接去搜第r个线性基,但要保持时间比l要大,新增了一个pos数组代表一个数插入时的时间戳,插入的时候如果可以替换那么就用之后的替换之前的,保证线性基中都是最新的元素,可以直接插入即可以直接插入 #include<cstdio> #include<iostream> #include<algorithm> #include<cstring&

2019杭电多校第九场

2019杭电多校第九场 熟悉的后半场挂机节奏,又苟进首页了,很快乐 1001. Rikka with Quicksort upsolved 不是我做的,1e9调和级数分段打表 1002. Rikka with Cake solved at 01:11 有一个矩形,给你很多射线(射线只有横平竖直的四个方向),问把矩形切成了多少块 队友说答案是交点数加一,作为一个合格的工具人,当然是把队友的想法实现啦 二维坐标离散化枚举纵坐标维护横坐标,常规套路,树状数组也可以做(我是线段树写习惯了根本没想起来还有

2019 杭电多校 第九场

2019 Multi-University Training Contest 9 补题链接:2019 Multi-University Training Contest 9 1005 Rikka with Game (HDU 6684) 题意 Rikka 和 Yuta 玩游戏.给定一个字符串.两人轮流对字符串操作.可以选择结束游戏,也可以改变其中一个字符,改变规则是:\(a\rightarrow b,b\rightarrow c,-,y\rightarrow z,z\rightarrow a.\