A:Birthday

时间限制: 1 Sec  内存限制: 256 MB

题目描述

恬恬的生日临近了。宇扬给她准备了一个大蛋糕。

正如往常一样,宇扬在蛋糕上插了n支蜡烛,并把蛋糕分为m个区域。因为某种原因,他必须把第i根蜡烛插在第ai个区域或第bi个区域。区域之间是不相交的。宇扬在一个区域内同时摆放x支蜡烛就要花费x2的时间。宇扬布置蛋糕所用的总时间是他在每个区域花的时间的和。

宇扬想快些见到恬恬,你能告诉他布置蛋糕最少需要多少时间吗?

输入

第一行包含两个整数nm(1 ≤ n ≤ 50, 2 ≤ m ≤ 50)。

接下来n行,每行两个整数ai, bi(1 ≤ ai, bim)。

输出

一个整数表示答案.

样例输入

3 3
1 2
1 2
1 2

样例输出

5

唉,还是大佬的题解写的好,所以感谢wls大佬分享思路  Orz。。。

思路:考虑费用流时把每个part拆成n个点,选择第i个点的代表为放置i块蛋糕和(i - 1)块蛋糕的时间差,

这个时间差是递增的,因此在费用流的过程中必定会从小到大选择

具体建图:

左边n个点代表n个蛋糕,右边m * n个点代表m个part,每个part拆成n个点。源点向每个左边的点连一条流量1费用0的边,每个右边的点向汇点连一条流量1费用0的编。

每个蛋糕向可以放的两个part的所有点连边,连向第i个点的费用为i^2 - (i - 1)^2,流量为1。这样求最小费用流既为答案。

#include"bits/stdc++.h"
using namespace std;
#define M 1100
const int inf=0x7fffffff;
struct node{
int u,v,c,f,next; //C为花费,F为flow流量
}e[M*40];
int pre[M],dis[M],head[M],t;
int vis[M]; void add1(int u,int v,int c,int f){
e[t].u=u;
e[t].v=v;
e[t].c=c;
e[t].f=f;
e[t].next=head[u];
head[u]=t++;
} void add(int u,int v,int c,int f){
add1(u,v,c,f);
add1(v,u,-c,0); //反向边流量初始为零,如果走反向边费用正好和原边抵消
} int spfa(int s,int t){
int i,u,v;
queue<int>q;
q.push(s);
memset(vis,0,sizeof(vis));
memset(pre,-1,sizeof(pre));
for(i=s;i<=t;i++)
dis[i]=inf;
dis[s]=0;
while(!q.empty()){
u=q.front();
q.pop();
for(i=head[u];i!=-1;i=e[i].next)
{
v=e[i].v;
if(e[i].f&&dis[v]>dis[u]+e[i].c) //找到一条最小费用流
{
dis[v]=dis[u]+e[i].c;
pre[v]=i; //记录路径
if(!vis[v])
{
vis[v]=1;
q.push(v);
}
}
}
vis[u]=0;
}
if(dis[t]!=inf)
return 1;
return 0;
} void solve(int s,int t){
int ans=0,i,j;
int flow=0,cost=0; //总流量、总费用
while(spfa(s,t)){
int minf=inf;
for(i=pre[t];i!=-1;i=pre[e[i].u]){
if(e[i].f<minf)
minf=e[i].f;
}
flow+=minf; //该条路径的流量
for(i=pre[t];i!=-1;i=pre[e[i].u]){
j=i^1;
e[i].f-=minf;
e[j].f+=minf;
}
cost+=dis[t]*minf; //单位运费和乘以流量得费用
}
printf("%d\n",cost);
}
int main(){
int i,u,v,c,n,m;
while(scanf("%d%d",&n,&m)==2){
t=0;
memset(head,-1,sizeof(head));
for(i=1;i<=n;i++){
scanf("%d%d",&u,&v);
add(0,i,0,1);
add(i,u+n,0,1);
add(i,v+n,0,1);
}
for(int i=1 ; i<=m ; ++i){
for(int j=1 ; j<=99 ; j+=2){//99 = 2*50-1;
add(i+n,n+m+1,j,1);
}
}
solve(0,n+m+1);
}
return 0;
}

B: Board

时间限制: 1 Sec  内存限制: 256 MB

题目描述

恬恬有一个n × n的数组。她在用这个数组玩游戏:

开始时,数组中每一个元素都是0。

恬恬会做某些操作。在一次操作中,她可以将某一行的所有元素同时加上一个值,也可以将某一列的所有元素同时加上一个值。

在几次操作后,一个元素被隐藏了。你能帮助她回忆隐藏的数是几吗?

输入

第一行一个整数n(1 ≤ n ≤ 1000)。

接下来n行每行n个整数表示数组a

第(i + 1)行的第j个元素表示aijaij =  - 1或0 ≤ aij ≤ 10000)。 - 1表示隐藏的元素。

输出

仅一个整数表示答案。

样例输入

3
1 2 1
0 -1 0
0 1 0

样例输出

1

这题思路同样为wls大佬给出,Orz wls 。。。

把格子N染色,第i行第j列格子的颜色为(i + j) % N。那么每次操作时,必定是N种不同的颜色都有一格被操作到,

因此最后任何颜色格子的和必定是相等的。因此只需要记录每种颜色格子的和,

并算出缺失格子的颜色C,用其余颜色的和减去颜色C的和即可

#include<bits/stdc++.h>

using namespace std;
int arr[1010][1010];
int a[1010], b[1010]; int main()
{
int n;
while(~scanf("%d", &n)){
memset(a, 0, sizeof(a));
memset(b, 0, sizeof(b));
int maxn = 10010, x, y;
for(int i = 1; i <= n; i++) {
maxn = 10010;
for(int j = 1; j <= n; j++) {
scanf("%d", &arr[i][j]);
if(arr[i][j] != -1){
maxn = min(maxn, arr[i][j]);
}
if(arr[i][j] == -1) {
x = i;
y = j;
}
}
a[i] = maxn;
}
int maxm;
for(int i = 1; i <= n; i++) {
int maxm = 10010;
for(int j = 1; j <= n; j++) {
if(arr[j][i] != -1){
maxm = min(maxm, arr[j][i]);
}
}
b[i] = maxm;
}
if(x == 1 && y == 1)cout << (a[x] + b[y]) - max((a[x+1]+b[y] - arr[x+1][y]),(a[x]+b[y+1]-arr[x][y+1])) << endl;
else if(x==n && y==1)cout << (a[x] + b[y]) - max((a[x-1]+b[y] - arr[x-1][y]),(a[x]+b[y+1]-arr[x][y+1])) << endl;
else if(x==1&&y==n)cout << (a[x] + b[y]) - max((a[x]+b[y-1] - arr[x][y-1]),(a[x+1]+b[y]-arr[x+1][y])) << endl;
else if(x==n&&y==n)cout << (a[x] + b[y]) - max((a[x-1]+b[y] - arr[x-1][y]),(a[x]+b[y-1]-arr[x][y-1])) << endl;
else if(x==1)cout << (a[x] + b[y]) - (a[x+1]+b[y]-arr[x+1][y]) << endl;
else if(x==n)cout << (a[x] + b[y]) - (a[x-1]+b[y]-arr[x+1][y]) << endl;
else cout << (a[x] + b[y]) - (a[x+1]+b[y] - arr[x+1][y]) << endl;
}
return 0;
}

D: Growth

时间限制: 1 Sec  内存限制: 256 MB

题目描述

弱弱有两个属性ab,这两个属性初始的时候均为0,每一天他可以通过努力,让a涨1点或b涨1点。

为了激励弱弱努力学习,我们共有n种奖励,第i种奖励有xiyizi三种属性,若axibyi,则弱弱在接下来的每一天都可以得到zi的分数。

问m天以后弱弱最多能得到多少分数。

输入

第一行一个两个整数nm(1 ≤ n ≤ 1000,1 ≤ m ≤ 2000000000)。

接下来n行,每行三个整数xiyizi(1 ≤ xi, yi ≤ 1000000000,1 ≤ zi ≤ 1000000)。

输出

一行一个整数表示答案。

样例输入

2 4
2 1 10
1 2 20

样例输出

50

提示

在样例中,弱弱可以这样规划:第一天a涨1,第二天b涨1,第三天b涨1,第四天a涨1。

共获得0 + 0 + 20 + 30 = 50分。

Orz wls。。。

把奖励的x拿出来从小到大排序,得到x1,x2,...,xn。

把奖励的y拿出来从小到大排序,得到y1,y2,...,yn。

用v[i][j]表示a值到达xi,b值达到yi时接下来每天可以得到的奖励。

v[i][j] = v[i - 1][j] + v[i][j - 1] - v[i - 1][j - 1] + t[i][j]

其中t[i][j]为满足x=i,y=j的奖励的总和。

用f[i][j]表示a值达到xi,b值达到yj时已经拿到的奖励的最大值。

f[i][j] + (x[i + 1] - x[i] - 1) * t[i][j] + t[i + 1][j] -> f[i + 1][j]

f[i][j] + (y[j + 1] - y[j] - 1) * t[i][j] + t[i][j + 1] -> f[i][j + 1]

最后统计一下答案就可以了。

不过这题有一个离散化不好写,我也是借鉴大佬的写法,

#include<bits/stdc++.h>
using namespace std; #define ios1 ios::sync_with_stdio(0)
#define ios2 cin.tie(0)
#define ll long long
#define inf 0x7ffffffff
typedef pair<int, int> P;
map<P, int>mp;
set<int>sx, sy; const int maxn = 1200; int n, m;
int xx[maxn], yy[maxn];
ll dp[maxn][maxn], v[maxn][maxn];
int x[maxn], y[maxn], z[maxn]; int main() {
ios1; ios2;
while(cin >> n >> m) {
int xi = 1, yi = 1;
for(int i = 0; i < n; i++) {
cin >> x[i] >> y[i] >> z[i];
if(mp.count(P(x[i], y[i])) == 0)mp[P(x[i], y[i])] = z[i];
else mp[P(x[i], y[i])] += z[i];
if(sx.count(x[i]) == 0){sx.insert(x[i]);xx[xi++] = x[i];}
if(sy.count(y[i]) == 0){sy.insert(y[i]);yy[yi++] = y[i];}
}
sort(xx, xx + xi);
sort(yy, yy + yi);//离散化
memset(dp, 0, sizeof(dp));
memset(v, 0, sizeof(v));
for(int i = 1; i < xi; i++) {
for(int j = 1; j < yi; j++) {
if(mp.count(P(xx[i], yy[j])) == 0)v[i][j] = v[i-1][j] + v[i][j-1] - v[i-1][j-1];
else v[i][j] = v[i-1][j] + v[i][j-1] - v[i-1][j-1] + mp[P(xx[i], yy[j])];
}
}
for(int i = 0; i < xi; i++) {
for(int j = 0; j < yi; j++) {
dp[i+1][j] = max(dp[i+1][j], dp[i][j] + (xx[i+1] - xx[i] - 1) * v[i][j] + v[i+1][j]);
dp[i][j+1] = max(dp[i][j+1], dp[i][j] + (yy[j+1] - yy[j] - 1) * v[i][j] + v[i][j+1]);
}
}
ll ans = 0;
for(int i = 1; i < xi; i++) {
for(int j = 1; j < yi; j++) {
ll r = dp[i][j] + (m - xx[i] - yy[j]) * v[i][j];
ans = max(ans, r);
}
}
cout << ans << endl;
}
return 0;
}

CCPC-Wannafly Summer Camp #1(部分解题报告)的更多相关文章

  1. 2020 CCPC Wannafly Winter Camp Day1 C. 染色图

    2020 CCPC Wannafly Winter Camp Day1 C. 染色图 定义一张无向图 G=⟨V,E⟩ 是 k 可染色的当且仅当存在函数 f:V↦{1,2,⋯,k} 满足对于 G 中的任 ...

  2. CCPC Wannafly Winter Camp Div2 部分题解

    Day 1, Div 2, Prob. B - 吃豆豆 题目大意 wls有一个\(n\)行\(m\)列的棋盘,对于第\(i\)行第\(j\)列的格子,每过\(T[i][j]\)秒会在上面出现一个糖果, ...

  3. 2020 CCPC Wannafly Winter Camp Day1 Div.1&amp F

    #include<bits/stdc++.h> #define forn(i, n) for (int i = 0; i < int(n); i++) #define fore(i, ...

  4. 2020 CCPC Wannafly Winter Camp Day1 - I. K小数查询(分块)

    题目链接:K小数查询 题意:给你一个长度为$n$序列$A$,有$m$个操作,操作分为两种: 输入$x,y,c$,表示对$i\in[x,y] $,令$A_{i}=min(A_{i},c)$ 输入$x,y ...

  5. 2020 CCPC Wannafly Winter Camp Day2-K-破忒头的匿名信

    题目传送门 sol:先通过AC自动机构建字典,用$dp[i]$表示长串前$i$位的最小代价,若有一个单词$s$是长串的前$i$项的后缀,那么可以用$dp[i - len(s)] + val(s)$转移 ...

  6. 2020 CCPC Wannafly Winter Camp Day1-F-乘法

    题目传送门 sol:二分答案$K$,算大于$K$的乘积有多少个.关键在于怎么算这个个数,官方题解上给出的复杂度是$O(nlogn)$,那么计算个数的复杂度是$O(n)$的.感觉写着有点困难,自己写了一 ...

  7. Mutual Training for Wannafly Union #1解题报告

    ---恢复内容开始--- q神等人组织的vjudge上的多校训练,题目基本上都来自于CF,#1是上周进行的,参加后感觉收获很多,因为上周准备期中比较忙,解题报告现在补上. 比赛地址(兼题目地址) A题 ...

  8. CH Round #56 - 国庆节欢乐赛解题报告

    最近CH上的比赛很多,在此会全部写出解题报告,与大家交流一下解题方法与技巧. T1 魔幻森林 描述 Cortana来到了一片魔幻森林,这片森林可以被视作一个N*M的矩阵,矩阵中的每个位置上都长着一棵树 ...

  9. 二模13day1解题报告

    二模13day1解题报告 T1.发射站(station) N个发射站,每个发射站有高度hi,发射信号强度vi,每个发射站的信号只会被左和右第一个比他高的收到.现在求收到信号最强的发射站. 我用了时间复 ...

  10. BZOJ 1051 最受欢迎的牛 解题报告

    题目直接摆在这里! 1051: [HAOI2006]受欢迎的牛 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 4438  Solved: 2353[S ...

随机推荐

  1. 使用vue实现行列转换的一种方法。

    行列转换是一个老生常谈的问题,这几天逛知乎有遇到了这个问题.一个前端说,拿到的数据是单列的需要做转换才能够绑定,折腾了好久才搞定,还说这个应该后端直接出数据,不应该让前端折腾. 这个嘛,行列转换在后端 ...

  2. 【网站公告】.NET Core 版博客站点第二次发布尝试

    在上次发布失败后,很多朋友建议我们改用 k8s ,但我们还是想再试试 docker swarm ,实在不行再改用 k8s . 在改进了 docker swarm 集群的部署后,我们准备今天 17:30 ...

  3. Oracle GoldenGate mysql To Kafka上车记录

    一.前言 首先要学习一下ogg的所有进程,看着这张图来学习   Manager进程是GoldenGate的控制进程,运行在源端和目标端上.它主要作用有以下几个方面:启动.监控.重启Goldengate ...

  4. JAVA基础知识(六)Java 静态多分派&动态单分派

    1.分派发生在编译期和运行期,编译期的分派为静态分派,运行期的为动态分派. 2.编译期是根据对象声明的类型来选择方法,运行期是根据对象实际类型来选择方法. 3.单分派和多分派取决于宗量, 方法调用者和 ...

  5. C#之反射、元数据详解

    前言 在本节中主要讲述自定义特性.反射和动态编程.自定义特性允许把自定义元数据与程序元素关联起来.这些元数据是在编译过程中创建的,并嵌入程序集中.反射是一个普通的术语,它描述了在运行过程中检查和处理程 ...

  6. 8.12 day31 进程间通信 Queue队列使用 生产者消费者模型 线程理论 创建及对象属性方法 线程互斥锁 守护线程

    进程补充 进程通信 要想实现进程间通信,可以用管道或者队列 队列比管道更好用(队列自带管道和锁) 管道和队列的共同特点:数据只有一份,取完就没了 无法重复获取用一份数据 队列特点:先进先出 堆栈特点: ...

  7. C# 读取CAD文件缩略图(DWG文件)

    //C# 读取CAD文件缩略图(DWG文件) https://blog.csdn.net/hanghangaidoudou/article/details/8589574 //2010-09-04 1 ...

  8. Throughput Controller

    吞吐量控制器(Throughput Controller)介绍 作用:控制其子节点的执行次数与负载比例分配 Total Executions: 整个测试计划中的总执行次数 Percent Execut ...

  9. 《统计学习方法》极简笔记P2:感知机数学推导

    感知机模型 输入空间是$\chi\subseteq\mathbb{R}^n$,输出空间是$y={+1,-1}$ 感知机定义为:$f(x)=sign(wx+b)$ 感知机学习策略 输入空间任一点$x_0 ...

  10. Ubuntu 图形界面入门

    Ubuntu 图形界面入门 一.目标 熟悉 Ubuntu 图形界面的基本使用 二..Ubuntu 的任务栏 三. 窗口操作按钮 四. 窗口菜单条