codeforces round #257 div2 C、D

本来应该认真做这场的,思路都是正确的。

C题,是先该横切完或竖切完,无法满足刀数要求,再考虑横切+竖切(竖切+横切),

因为横切+竖切(或竖切+横切)会对切割的东西产生交叉份数,从而最小的部分不会尽可能的大。

代码如下,虽然比较长、比较乱,但完全可以压缩到几行,因为几乎是4小块重复的代码,自己也懒得压缩

注意一点,比如要判断最小块的时候,比如9行要分成2份,最小的剩下那份不是9取模2,而应该是4

m/(k+1)<=m-m/(k+1)*k

        

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int MAX = 1e6+10;
const LL MOD = 1e9+7;
LL f[1000];
int main() {
    LL n,m,k;
    //freopen("in.txt", "r", stdin);
    while(scanf("%I64d %I64d %I64d",&n,&m, &k)==3) {
        if(k > (n+m-2)) { printf("-1\n"); continue;}
        LL k1 = k;
        LL ans = 0, ans2 = 0;
        if(1){
            if(k<=(m-1)){
              if(m%(k+1)==0)
                ans = m/(k+1)*n;
              else if(m/(k+1)<=m-m/(k+1)*k) {
                ans = m/(k+1)*n;
              }
              else ans = (m/(k+1)-1)*n;
            }
            else {
                k -= (m-1);
                if(n%(k+1)==0)
                    ans = n/(k+1);
                else if(m/(k+1)<=m-m/(k+1)*k) {
                    ans = n/(k+1);
                }
                else ans = (n/(k+1)-1);
            }
        }
        //printf("%I64d~\n", ans);
        swap(n, m);
        if(2){
            k = k1;
            if(k<=(m-1)){
              if(m%(k+1)==0) {
                ans2 = m/(k+1)*n;
              }
              else if(m/(k+1)<=m-m/(k+1)*k) {
                ans2 = m/(k+1)*n;
              }
              else ans2 = (m/(k+1)-1)*n;
            }
            else {
                k -= (m-1);
                if(n%(k+1)==0)
                    ans2 = n/(k+1);
                else if(m/(k+1)<=m-m/(k+1)*k) {
                    ans2 = n/(k+1);
                }
                else ans2 = (n/(k+1)-1);
            }
        }

        printf("%I64d\n", max(ans, ans2));
    }
}

D题

一看题目时就很欣喜,挺有意思的图论。

一开始的思路是错的,每次进行松弛操作时判断当前边是否标记过,从而进行减减操作,这样考虑忘了后面可能进行了一些更新,从而覆盖了前面的标记

正确思路:

在每次优先队列出点的时候,判断从起点到这个点的最短路有多少是跟K条(train route)是重复的即可

自己需要注意的地方:

1、怎样记录最短路的数目

2、当k==Count[u]时候的处理

 3、小细节,第一个节点u,tt与Count[u]都是等于0的

代码还是挺快的~

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>

using namespace std;

#define clr(x) memset(x,0,sizeof(x))
#define fp1 freopen("in.txt","r",stdin)
#define fp2 freopen("out.txt","w",stdout)
#define pb push_back

#define INF 0x3c3c3c3c
typedef long long LL;

const int maxn = 4*1e5;
bool vis[maxn];
struct Edge {int from,to,dist,cnt;};
struct Node
{
    int d,u;
    bool operator <(const Node &a) const {
        return a.d<d;   //从小到大排序。
    }
};

int n,m,k; //点数和边数,用n表示,e不能和m冲突
vector<Edge> edges;//边列表
vector<int> G[maxn];//每个结点出发的边编号(从0开始编号)
vector<int> qw[maxn];
int Count[maxn];
bool done[maxn];//是否已永久编号
int d[maxn];//s到各个点的距离
int p[maxn];//最短路中的上一条边
void init()
{
    for(int i=0;i<n;i++) G[i].clear();//清空邻接表
    edges.clear();
}

void addedge(int from,int to,int dist)
//如果是无向,每条无向边需调用两次addedge
{
    edges.push_back((Edge){from,to,dist});
    int temp=edges.size();
    G[from].push_back(temp-1);
}

void dijk(int s)
{

    clr(Count);
    priority_queue<Node> q;
    for(int i=0;i<n;i++) d[i]=INF;
    d[s]=0;
    memset(done,0,sizeof(done));
    q.push((Node){0,s});
    while(!q.empty()) {
        Node x=q.top();
        q.pop();
        int u=x.u;
        if(done[u]) continue;
        done[u]=true;
        for(int i=0;i<G[u].size();i++) {
            Edge &e=edges[G[u][i]];
            if(d[e.to]>d[u]+e.dist) {
                d[e.to]=d[u]+e.dist;
                p[e.to]=G[u][i];
                q.push((Node){d[e.to],e.to});
                Count[e.to] = 1;
            }
            else if(d[e.to]==d[u]+e.dist){
                Count[e.to] ++;
            }
        }

        int tt = 0;
        for(int i = 0;i < qw[u].size();i++){
            if(qw[u][i] > d[u]) {
                //printf("%d %d %d~\n", u, qw[u][i], d[u]);
                int temp = k -1;
                k = temp;
            }
            else if(qw[u][i] == d[u]) tt++;
        }
        //printf("%d %d %d!\n", u, tt, Count[u]);
        if(tt == 0) continue;
        else if(tt < Count[u]) {  k -= tt; }
        else if(tt == Count[u]) k -= (tt-1);
    }
}

int main()
{
    //fp1;
    while(scanf("%d %d %d", &n, &m, &k) == 3){
        int k1 = k;
        init();
        int u, v, w;
        for(int i = 1;i <= m;i++){
            scanf("%d %d %d", &u, &v, &w);
            u--; v--;
            addedge(u, v, w);
            addedge(v, u, w);
        }
        for(int i = m+1;i <= m+k;i++){
            scanf("%d %d", &u, &v);
            u--;
            addedge(0, u, v);
            addedge(u, 0, v);
            qw[u].pb(v);
        }
        dijk(0);
        printf("%d\n", k1 - k);
    }
    return 0;
}

codeforces round #257 div2 C、D,布布扣,bubuko.com

时间: 2024-12-24 02:09:22

codeforces round #257 div2 C、D的相关文章

Codeforces Round #257 (Div. 2) A/B/C/D

前三题早就写好了,一直在纠结D A. Jzzhu and Children 题意:就是简单的模拟,给排成一队的孩子分发糖果,每个孩子有至少要得到的糖果数. 然后每次给队头的孩子分发m个糖果,如果他已经得到了足够的糖果(大于等于他想得到的 最少糖果数)那么他就出队,否则他就去队尾.问最后一个孩子的编号. 算法:队列模拟,水题~ #include<cstdio> #include<iostream> #include<cstring> #include<queue&g

Codeforces Round #289 Div2 E

Problem 给一串长度为N的字符串,对于每个字符,若字符为元音,则权值为1,否则为0.一个子串的权值定义为该串所有字符权值之和除以字符个数,一个母串的权值定义为所有子串的权值之和.求母串的权值. Limits Time Limit(ms): 1000 Memory Limit(MB): 256 N: [1, 5*10^5] 字符集: 'A'-'Z' 元音: I E A O U Y Solution 考虑每个元音字符对母串的贡献,可以找出规律. More 举"ABCDOEFGHKMN"

Codeforces Round #257 (Div. 2)

A.Jzzhu and Children 计算每个人会出现的轮次数,取最后一个且轮次数最大的,注意是用a[i]-1 % m,倒着扫一遍就行了 #include <iostream> #include <cstdio> #include <cstdlib> using namespace std; const int maxn = 100+10; int n, m; int a[maxn]; int main() { #ifdef LOCAL freopen("

Codeforces Round #257 (Div. 2) E题:Jzzhu and Apples 模拟

E. Jzzhu and Apples time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output Jzzhu has picked n apples from his big apple tree. All the apples are numbered from 1 to n. Now he wants to sell them to

codeforces Round #250 (div2)

a题,就不说了吧 b题,直接从大到小排序1-limit的所有数的lowbit,再从大到小贪心组成sum就行了 1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #define N 200000 6 using namespace std; 7 int pos[N],a[N],s[N],f[N],la[N],b[N],i,j,k,ans,n,p

Codeforces Round #257 div.2 D or 450D Jzzhu and Cities【最短路】

Codeforces Round #257 div.2 D or 450D Jzzhu and Cities[最短路] 题目链接:点击打开 题目大意: 在一个国家中有n个城市(城市编号1~n),m条公路和k条铁路,编号为1的城市为首都,为了节约,不需要的铁路需要关闭,问在保证首都到其余所有城市的最短路不变的条件下,最多有多少条铁路是不需要的. 解法: 这个题比较麻烦,保证首都到其余城市的最短路不变,要求出最多有多少条铁路是不需要的,那肯定是从最短路的代码上下手了,我们首先考虑dijkstra算法

Codeforces Round#320 Div2 解题报告

Codeforces Round#320 Div2 先做个标题党,骗骗访问量,结束后再来写咯. codeforces 579A Raising Bacteria codeforces 579B Finding Team Member codeforces 579C A Problem about Polyline codeforces 579D "Or" Game codeforces 579E Weakness and Poorness codeforces 579F LCS Aga

Codeforces Round #254(div2)A

很有趣的题.想到了就非常简单,想不到就麻烦了. 其实就是一种逆向思维:最后结果肯定是这样子: WBWBWBWB... BWBWBWBW... WBWBWBWB... ... 里面有“-”的地方改成“-”就行了. 但是我开始是正着想的,想每个点怎么处理,这还要看它周围点的状态,越想越麻烦... 这题中体现的正难则反的逆向思维很值得学习. #include<iostream> #include<cstdio> #include<cstdlib> #include<cs

Codeforces Round #254(div2)B

就是看无向图有几个连通块,答案就是2n-num. 范围很小,就用矩阵来存图减少代码量. #include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<map> #include<set> #include<vector> #include<algorithm> #inc