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. 无法正常卸载pr

    控制面板找不到pr和ps,根本无法卸载,我试过官方工具没用,也试过ccleaner,也检测不到?

  2. IDED中配置SVN没有svn.exe解决办法

    首先在idea中配置svn时

  3. 统计学习方法—SVM推导

    目录 SVM 1. 定义 1.1 函数间隔和几何间隔 1.2 间隔最大化 2. 线性可分SVM 2.1 对偶问题 2.2 序列最小最优算法(SMO) 3. 线性不可分SVM 3.1 松弛变量 3.2 ...

  4. k8s学习笔记

    9.deployment:声明式的升级应用 9.1.使用RC实现滚动升级 #kubectl rolling-update kubia-v1 kubia-v2 --image=luksa/kubia:v ...

  5. Elasticsearch6.x和7.x版本常用插件汇总

    elasticsearch插件汇总 基于es 7.3版本试用. 一.安全插件 1.x-pack a.介绍 包括安全(x-pack-security),监视(x-pack-watcher),警报(x-p ...

  6. spring-boot-plus 常见问题解决 FAQ(十二)

    spring-boot-plus 常见问题解决 FAQ 编译错误问题 log日志编译错误 编译提示log.info等日志错误 解决 检查是否安装lombok插件 idea安装lombok eclips ...

  7. Redis集群环境下的键值空间监听事件实现方案

    一直想记录工作中遇到的问题和解决的方法,奈何没有找到一方乐土,最近经常反思,是否需要记录平时的点滴,后台还是决定下定决心记录一些,以便以后用到的时候找不着,实现这样的一个功能主要也是业务所需要的. 需 ...

  8. springBoot框架分布式部署定时任务重复执行之解决方案

    问题描述: 在集群模式部署服务端时,会出现所有的定时任务在各自的节点处均会执行一遍,这显然不符合实际的开发场景,针对这种问题,本文给出一种springboot集成shedlock的解决方案 第一步:引 ...

  9. Kibana 管理界面使用教程

    使用浏览器访问 ip:5601 默认端口,进入首页 Discover:日志管理视图 Visualize:统计视图 Dashboard:仪表视图 Timelion:时间轴视图 APM:性能管理视图 De ...

  10. Python之高阶函数如何理解?

    我们先要了解一下什么是所谓的高阶函数: 看定义:什么是高阶函数? 高阶函数:我们知道一个函数可以作为参数传给另外一个函数,或者一个函数的返回值为另外一个函数(若返回值为该函数本身,则为递归),如果满足 ...