2017 ZSTU寒假排位赛 #3
题目链接:https://vjudge.net/contest/147974#overview。
A题,费用流,不会。。跳过了。
B题,给一个图,问至少添加几条边能成为强连通图。显然缩点,要使得成为一个scc,任意一个点都要至少一个入度和出度,而一条边可以提供一个入度和出度,因为答案为max(入度为0的点,出度为0的点)。如果要求最多能添加几条使得还不是scc,则参照:最多添加几条使得还不是scc。如果是无向图问至少添加几条使得是边双联通,则参照:至少添加几条使得边双联通。
C题,线段树区间合并,貌似暑假的时候写过类似的,但是忘记了。。代码如下:
//#include <bits/stdc++.h>
#include <stdio.h>
#include <algorithm>
#include <string.h>
#define t_mid (l+r>>1)
#define ls (o<<1)
#define rs (o<<1|1)
#define lson ls,l,t_mid
#define rson rs,t_mid+1,r
using namespace std;
const int N = + ; int a[N];
// sub表示节点o的lcis的最长长度,l_val和r_val分别表示这个节点最左边和最右边的值分别是多少
// l_sub表示这个节点从最左边开始的最长的lcis的长度,r_sub同
int sub[N<<],l_val[N<<],r_val[N<<],l_sub[N<<],r_sub[N<<];
int T,n,q;
void up(int o,int l,int r)
{
int len = r - l + ;
l_val[o] = l_val[ls], r_val[o] = r_val[rs]; // 更新l_val,r_val
// 更新sub的值
sub[o] = max(sub[ls], sub[rs]);
if(r_val[ls] < l_val[rs]) sub[o] = max(sub[o], r_sub[ls]+l_sub[rs]); // 更新l_sub,r_sub
l_sub[o] = l_sub[ls];
if(l_sub[o] == len-len/ && r_val[ls] < l_val[rs]) l_sub[o] += l_sub[rs]; r_sub[o] = r_sub[rs];
if(r_sub[o] == len/ && r_val[ls] < l_val[rs]) r_sub[o] += r_sub[ls];
}
void build(int o,int l,int r)
{
if(l == r)
{
sub[o] = l_sub[o] = r_sub[o] = ;
l_val[o] = r_val[o] = a[l];
return ;
}
build(lson);
build(rson);
up(o,l,r);
}
void update(int o,int l,int r,int pos,int x)
{
if(l == r)
{
l_val[o] = r_val[o] = x;
return ;
}
if(pos <= t_mid) update(lson,pos,x);
else update(rson,pos,x);
up(o,l,r);
}
int query(int o,int l,int r,int ql,int qr)
{
if(l == ql && r == qr) return sub[o];
int ans = ;
if(qr <= t_mid) ans = query(lson,ql,qr);
else if(ql > t_mid) ans = query(rson,ql,qr);
else
{
ans = max(query(lson,ql,t_mid), query(rson,t_mid+,qr));
// 注意下面一行的两个min
if(r_val[ls] < l_val[rs]) ans = max(ans, min(r_sub[ls], t_mid-ql+) + min(l_sub[rs], qr-t_mid));
}
return ans;
} int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&q);
for(int i=;i<=n;i++) scanf("%d",a+i);
build(,,n);
while(q--)
{
char s[];
int x,y;
scanf("%s%d%d",s,&x,&y);
if(s[] == 'U') update(,,n,x+,y);
else printf("%d\n",query(,,n,x+,y+));
}
}
return ;
}
线段树区间合并
D题,分组背包,每组中,先选择一个,然后该组中其他的有三个选择,不选,或者从之前一组中转移(也就是放弃了这组中第一个选的而选这组中的这个),或者从这组中的转移(这组中的第一个要选)。代码如下:
#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <iostream>
#include <stdlib.h>
#include <string>
#include <stack>
using namespace std;
const int inf = 0x3f3f3f3f;
typedef long long ll;
typedef pair<int,int> pii;
const int N = + ; int n,m,k;
vector<pii> v[];
int dp[][+]; int main()
{
while(scanf("%d%d%d",&n,&m,&k) == )
{
for(int i=;i<=k;i++) v[i].clear();
for(int i=;i<=n;i++)
{
int pos,mo,val;
scanf("%d%d%d",&pos,&mo,&val);
v[pos].push_back(pii(mo,val));
}
int sum = ;
int flag = ;
for(int i=;i<=k;i++)
{
if(v[i].size() == )
{
flag = ;
break;
}
sort(v[i].begin(), v[i].end());
sum += v[i][].first;
}
if(sum > m || flag == )
{
printf("Impossible\n");
continue;
}
memset(dp,,sizeof dp);
for(int i=;i<=k;i++)
{
for(int j=;j<v[i].size();j++)
{
int w = v[i][j].first, val = v[i][j].second;
for(int mask=m;mask>=w;mask--)
{
if(j == ) dp[i][mask] = dp[i-][mask-w] + val;
else dp[i][mask] = max({dp[i][mask], dp[i-][mask-w]+val, dp[i][mask-w]+val});
}
}
}
printf("%d\n",dp[k][m]);
}
}
分组背包
E题,直接暴力枚举即可。完全背包也行。第一次wa是因为认为贪心先拿最小的最优,其实不然。例如:53--10,11,23。显然11的拿3个再拿10的两个比较好。
2017 ZSTU寒假排位赛 #3的更多相关文章
- 2017 ZSTU寒假排位赛 #7
题目链接:https://vjudge.net/contest/149498#overview. A题,水题,直接按照题意模拟一下即可. B题,我用的是线段树.大力用的差分标记(上次听zy说过,下次再 ...
- 2017 ZSTU寒假排位赛 #1
题目链接:https://vjudge.net/contest/147102#overview. A题:给出一堆的点,要找出两条垂直的直线,一条与x轴呈45度.-->使得所有的点到任意一条直线的 ...
- 2017 ZSTU寒假排位赛 #2
题目链接:https://vjudge.net/contest/147632#overview. A题,状态压缩一下然后暴力即可. B题,水题,略过. C题,有负数,前缀和不是单调的,因此不能用尺取法 ...
- 2017 ZSTU寒假排位赛 #8
题目链接:https://vjudge.net/contest/149845#overview. A题,水题. B题,给出 p个 第一个人的区间 和 q个第二个人的区间,问[l,r]中有多少个整数满足 ...
- 2017 ZSTU寒假排位赛 #6
题目链接:https://vjudge.net/contest/149212#overview. A题,水题,略过. B题,水题,读清题意即可. C题,数学题,如果把x表示成x=nb+m,则k=n/m ...
- 2017 ZSTU寒假排位赛 #5
题目链接:https://vjudge.net/contest/148901#overview. A题,排序以后xjbg即可. B题,弄个数组记录当前列是不是删除以及当前行是不是已经大于下一行然后乱搞 ...
- 2017 ZSTU寒假排位赛 #4
题目链接:https://vjudge.net/contest/148543#overview. A题:n个罪犯,每个人有一个犯罪值,现在要从里面选出连续的c个人,每个人的犯罪值都不能超过t,问选法的 ...
- Codeforces Round #341 (Div. 2)
在家都变的懒惰了,好久没写题解了,补补CF 模拟 A - Wet Shark and Odd and Even #include <bits/stdc++.h> typedef long ...
- 2017杭电ACM集训队单人排位赛 - 6
2017杭电ACM集训队单人排位赛 - 6 排名 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 59 1 X X 1 1 X X 0 1 ...
随机推荐
- 复习二叉数 pat l2-006 数的遍历
L2-006. 树的遍历 给定一棵二叉树的后序遍历和中序遍历,请你输出其层序遍历的序列.这里假设键值都是互不相等的正整数. 输入格式: 输入第一行给出一个正整数N(<=30),是二叉树中结点 ...
- Winform界面GridView中XCDataGridViewCheckBoxAllColumn改变触发事件
1.首先利用CurrentCellDirtyStateChanged事件 监测状态改变后判断是否有未提交的更改,若有则提交 private void CurrentCellDirtyStateChan ...
- JS中逗号运算符的用法
逗号运算符,它将先计算左边的参数,再计算右边的参数值.然后返回最右边参数的值. 原书举的例子不太好,无法解释上面那句话,这里另外提供一个: var a = 10, b = 20; function C ...
- 一个下午整理的Web前端常见的英文缩写
PV (Page View)页面浏览量 FED(Front-End Development)前端开发 F2E(Front-End Engineer)前端工程师 WWW(World Wide Web)万 ...
- docker 第四篇 网络
安装docker以后自动添加三种网络方式 bridge: 表示桥接网络 (在本地自动创建一个软交换机) host: 表示让容器使用宿主机的网络名称空间 none: 表示没有网络 不能执行网络通信. 创 ...
- ffmpeg 命令行 杂记
输入mp4文件中的音频每一帧的信息 ffprobe -show_streams -select_streams a -show_format -show_frames .\HYUNDAIMOBIS.m ...
- 遍历二叉树 - 基于队列的BFS
之前学过利用递归实现BFS二叉树搜索(http://www.cnblogs.com/webor2006/p/7262773.html),这次学习利用队列(Queue)来实现,关于什么时BFS这里不多说 ...
- git的安装和简单使用
目前windows版本的git有几种实现,但我们选择msysgit发行版,这是目前做得兼容性最好的. 下载地址: http://code.google.com/p/msysgit/downloads/ ...
- php 把数字拆分成数组
用str_split $a = 1234567890; //拆分数字为数组 var_dump( str_split($a, 1) ); 打印结果 : Array ( [0] =2 [1] =5 )
- python 前置程序窗口,还原最小化的窗口
python 前置程序窗口,还原最小化的窗口 在网上找了比较久,大多是: win32gui.FindWindow(class_name, window_name) win32gui.SetForegr ...