CCPC-Wannafly Winter Camp Day1 (Div2, online mirror) A,B,C,E,F,I,J
https://www.zhixincode.com/contest/7/problems
A题
分类讨论
当B有点需要经过时 穿梭的花费肯定为2*k,也可以发现,我们要找到包含所有需要经过的点(不含起点)的最小矩形,端点肯定是传送门,排序,找到需要经过最小的值和最大的值,再分别找小于等于和大于等于他们的传送门, 作为矩形端点,再判断起点的位置,最终得出答案。
当B无点需要经过时 分三种考虑,起点在最左边,最右边,在中间,很容易想到。
#include<bits/stdc++.h>
#define all(a) (a).begin(),(a).end()
using namespace std;
typedef unsigned long long ull;
const int maxn=2e6+;
int n,r,m,k,s;
int main()
{
scanf("%d%d%d%d%d",&n,&r,&m,&k,&s);
vector<int> x,y,zhuan{,n};
for(int i=;i<r;i++)
{
int a,b;
scanf("%d%d",&a,&b);
if(a==s&&b==)
continue;
if(b==)
x.push_back(a);
else
y.push_back(a);
}
sort(all(x));sort(all(y));
while(m--)
{
int c;
scanf("%d",&c);
zhuan.push_back(c);
}
sort(all(zhuan));
if(y.size()>)
{
int l,r;
if(x.size()==)
r=*(--y.end()),l=*y.begin();
else
{
r=max(*(--x.end()),*(--y.end()));
l=min(*x.begin(),*y.begin());
}
int ans1=zhuan[upper_bound(all(zhuan),l)-zhuan.begin()-];
int ans2=zhuan[lower_bound(all(zhuan),r)-zhuan.begin()];
int ans=(ans2-ans1+k)*;
if(s<ans1)
ans+=(ans1-s)*;
else if(s>ans2)
ans+=(s-ans2)*;
cout<<ans<<endl;
return ;
}
x.push_back(s);
sort(all(x));
if(x.size()==&&*x.begin()==s)
cout<<<<endl;
else if(*x.begin()==s)
{
int ans=zhuan[lower_bound(all(zhuan),*(--x.end()))-zhuan.begin()];
cout<<(ans-s)*<<endl;
}
else if(*(--x.end())==s)
{
int ans=zhuan[upper_bound(all(zhuan),*x.begin())-zhuan.begin()-];
cout<<(s-ans)*<<endl;
}
else
{
int ans1=zhuan[upper_bound(all(zhuan),*x.begin())-zhuan.begin()-];
int ans2=zhuan[lower_bound(all(zhuan),*(--x.end()))-zhuan.begin()];
cout<<(ans2-ans1)*<<endl;
}
}
//20 4 2 50 4
//7 0
//13 0
//15 1
//6 1
//5
//
B
dp dp[x][y][k]表示 第k秒 x,y 获得的最大值,初始化dp[xs][ys][0]=0其他数组为-inf 若干秒后 dp[x][y][k]>0 肯定是由起点转移过来的。
枚举时间找到满足的最小时间就好了。
#include<bits/stdc++.h>
#define all(a) (a).begin(),(a).end()
using namespace std;
typedef unsigned long long ull;
const int maxn=;
int mp[][],dp[][][maxn];
int main()
{
int n,m,C,xs,xt,ys,yt;
scanf("%d%d%d",&n,&m,&C);
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
scanf("%d",&mp[i][j]);
scanf("%d%d%d%d",&xs,&ys,&xt,&yt);
memset(dp,-0x3f,sizeof(dp));
dp[xs][ys][]=;
for(int k=;k<maxn;k++)
{
for(int i=;i<=n;i++)
{
for(int j=;j<=m;j++)
{
dp[i][j][k]=max({dp[i-][j][k-],dp[i][j+][k-],dp[i+][j][k-],dp[i][j-][k-],dp[i][j][k-]})+(k%mp[i][j]==?:);
}
}
}
int ans=-;
for(int i=;i<maxn;i++)
{
if(dp[xt][yt][i]>=C)
{
ans=i;
break;
}
}
printf("%d\n",ans); }
C 不会证,但是猜到了。。。
E
树形dp dp[x][0]表示不选x,dp[x][1]表示选择x,根据题意写状态转移方程就好了
#include <bits/stdc++.h>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define all(a) (a).begin(), (a).end()
#define fillchar(a, x) memset(a, x, sizeof(a))
#define huan printf("\n")
#define debug(a,b) cout<<a<<" "<<b<<" "<<endl
#define ffread(a) fastIO::read(a)
using namespace std;
typedef long long ll;
const int maxn = 1e5+;
const int maxm = 1e4+;
const int inf = 0x3f3f3f3f;
const ll mod = ;
const double epx = 1e-;
const double pi = acos(-1.0);
//head------------------------------------------------------------------
struct edge
{
int to,next;
}e[maxn];
int head[maxn],tot;
int dp[maxn][],vis[maxn],f[maxn],d[maxn],n;
void init()
{
tot=;
fillchar(head,-);
fillchar(vis,);
}
void add(int u,int v)
{
e[tot].to=v;
e[tot].next=head[u];
head[u]=tot++;
}
void dfs(int x,int y)
{
vis[x]=;
dp[x][]=;
dp[x][]=f[x];
for(int i=head[x];i!=-;i=e[i].next)
{
int v=e[i].to;
if(v==y)
continue;
dfs(v,x);
dp[x][]+=max(dp[v][],dp[v][]);
dp[x][]+=max(dp[v][],dp[v][]-d[min(x,v)]);
}
}
int main()
{
init();
cin>>n;
for(int i=;i<=n;i++)
cin>>f[i];
for(int i=;i<=n;i++)
cin>>d[i];
for(int i=;i<=n;i++)
{
if(i%==)
add(i/,i),add(i,i/);
else if(*i+<=n)
add(*i+,i),add(i,*i+);
}
int ans=;
for(int i=;i<=n;i++)
if(!vis[i])
{
dfs(i,-);
ans+=max(dp[i][],dp[i][]);
}
cout<<ans<<endl;
}
F最短路
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<bitset>
#include<cassert>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<deque>
#include<iomanip>
#include<list>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<vector>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<int,int> pii; const double PI=acos(-1.0);
const double eps=1e-;
const ll mod=1e9+;
const int inf=0x3f3f3f3f;
const int maxn=1e5+;
const int maxm=+;
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); int n,m,k;
int cnt=,head[maxn<<];
bool vist[maxn];
ll dis[maxn],body[maxn];
priority_queue<pair<ll,int>,vector<pair<ll,int> >,greater<pair<ll,int> > >q; struct node{
int v,nex;
ll w;
}edge[maxn<<]; void add(int u,int v,ll w)
{
edge[cnt].v=v;
edge[cnt].w=w;
edge[cnt].nex=head[u];
head[u]=cnt++;
} void dijkstra(int s)
{
dis[s]=;//到自己的最短距离直接设为0
q.push(make_pair(,s));
while(!q.empty()){//队列非空
int u=q.top().second;q.pop();
vist[u]=true;
for(int i=head[u];~i;i=edge[i].nex){
int v=edge[i].v;
ll w=edge[i].w+(body[v]>k?(body[v]-k)*(body[v]-k):);
if(dis[v]>dis[u]+w){//满足条件更新距离
dis[v]=dis[u]+w;
//p[v]=u;//保存路径
q.push(make_pair(dis[v],v));//把更新完的值压入队列
}
}
}
} int main()
{
memset(head,-,sizeof(head));//初始化数组
memset(vist,false,sizeof(vist));
//memset(dis,inf,sizeof(dis));
cin>>n>>m>>k;
for(int i=;i<=n;i++)
dis[i]=1e18;
for(int i=;i<=n;i++)
cin>>body[i];
for(int i=;i<=m;i++){
int u,v;ll w;
cin>>u>>v>>w;
add(u,v,w);
add(v,u,w);//无向图相互可达 有向图一次就好
}
k+=body[];
dijkstra();
cout<<dis[n]<<endl;
I 树状数组+dfs
解析 长度肯定是奇数3,5,7,9...然后会发现 长度5的是两个长度3的连起来,长度7的是三个长度3的连起来...
那我们就先来找长度为3的序列 枚举左右端点l r, 由于每个数的大小不超过2000,所以我们开2000个树状数组来记录小于j的个数
所以就有 if(a[l]>a[r]) 我们getsum(a[r],r)-getsum(a[r],l)得到(l,r) 区间中小于a[r]的个数k,然后 l - ->r 连一条有向边权值为k
复杂度O(n*n*log(n))
图建完之后dfs计数dp[i] 表示以i为起点的路径总数 从叶子向上递归。
1-->5-->10-->15 这条链的过程就是 dp[15]=0,dp[10]=dp[15]*2+2,dp[5]=dp[10]*4+4,dp[1]=dp[5]*3+3
枚举起点,采用记忆化来降低复杂度,O(n)。
这个解法不是最好的,其他大佬代码又短又快QAQ。
#include <bits/stdc++.h>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define all(a) (a).begin(), (a).end()
#define fillchar(a, x) memset(a, x, sizeof(a))
#define huan printf("\n")
#define debug(a,b) cout<<a<<" "<<b<<" "<<endl
#define ffread(a) fastIO::read(a)
using namespace std;
typedef long long ll;
const int maxn = 2e3+;
const int inf = 0x3f3f3f3f;
const ll mod = ;
const double epx = 1e-;
const double pi = acos(-1.0);
//head------------------------------------------------------------------
int a[maxn],c[maxn][maxn],tot,n,head[maxn],vis[maxn];
ll dp[maxn]; //对应原数组和树状数组
int lowbit(int x){
return x&(-x);
}
void updata(int j,int i,int k)
{
while(i <= n){
c[j][i] += k;
i += lowbit(i);
}
}
int getsum(int j,int i)
{ //求A[1 - i]的和
int res = ;
while(i > ){
res += c[j][i];
i -= lowbit(i);
}
return res;
}
struct edge
{
int to,val,next;
}e[maxn*maxn];
void add(int u,int v,int w)
{
e[tot].val=w;
e[tot].to=v;
e[tot].next=head[u];
head[u]=tot++;
}
void init()
{
tot=;
memset(head,-,sizeof(head));
memset(vis,,sizeof(vis));
}
void dfs(int x)
{
if(vis[x])
return;
for(int i=head[x];i!=-;i=e[i].next)
{
ll v=e[i].to,w=e[i].val;
dfs(v);
dp[x]=(dp[x]+dp[v]*w%mod+w)%mod;
}
vis[x]=;
}
int main()
{
init();
//freopen("C:\\Users\\HP\\Desktop\\a.txt","r",stdin);
scanf("%d",&n);
for(int i=;i<=n;i++)
{
scanf("%d",&a[i]);
for(int j=a[i]+;j<=n;j++)
updata(j,i,);
}
for(int i=;i<=n;i++)
{
for(int j=i+;j<=n;j++)
{
if(a[i]<a[j])continue;
int temp=getsum(a[j],j)-getsum(a[j],i);
if(temp)
add(a[i],a[j],temp);
}
}
ll ans=;
for(int i=;i<=n;i++)
{
dfs(a[i]);
ans=(ans+dp[a[i]])%mod;
}
printf("%lld\n",ans);
}
J 这题应该是cf原题了 做法是枚举答案。
CCPC-Wannafly Winter Camp Day1 (Div2, online mirror) A,B,C,E,F,I,J的更多相关文章
- 2020 CCPC Wannafly Winter Camp Day1 C. 染色图
2020 CCPC Wannafly Winter Camp Day1 C. 染色图 定义一张无向图 G=⟨V,E⟩ 是 k 可染色的当且仅当存在函数 f:V↦{1,2,⋯,k} 满足对于 G 中的任 ...
- Comet OJ CCPC-Wannafly Winter Camp Day1 (Div2, online mirror) F.爬爬爬山-最短路(Dijkstra)(两个板子)+思维(mdzz...) zhixincode
爬爬爬山 已经提交 已经通过 9.83% Total Submission:417 Total Accepted:41 题目描述 爬山是wlswls最喜欢的活动之一. 在一个神奇的世界里,一共有nn座 ...
- 2020 CCPC Wannafly Winter Camp Day1 Div.1& F
#include<bits/stdc++.h> #define forn(i, n) for (int i = 0; i < int(n); i++) #define fore(i, ...
- 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 ...
- CCPC-Wannafly Winter Camp Day1 (Div2 ABCFJ) 待补...
Day1 Div2 场外链接 按题目顺序~ A 机器人 传送门 题意:有两条平行直线A.B,每条直线上有n个点,编号为1~n.在同一直线上,从a站点到b站点耗时为两点间的距离.存在m个特殊站点,只有在 ...
- CCPC Wannafly Winter Camp Div2 部分题解
Day 1, Div 2, Prob. B - 吃豆豆 题目大意 wls有一个\(n\)行\(m\)列的棋盘,对于第\(i\)行第\(j\)列的格子,每过\(T[i][j]\)秒会在上面出现一个糖果, ...
- 2019 CCPC-Wannafly Winter Camp Day1 (Div2, onsite)
solve:4/11 补题:6/11 A 机器人 补题:zz 这是一道分类讨论的题目,有一个规律就是如果必须要从第一个区到第二个区,那么最多转区两次(1到2一次,2到1一次),然后分类讨论即可,只要细 ...
- CCPC-Wannafly Winter Camp Day1 (Div2, onsite) A B C E F I J
A 机器人 链接:https://www.cometoj.com/contest/7/problem/A?problem_id=92 思路: 分两大类讨论: 1. B区没有点: (1)点都在起点左边 ...
- CCPC-Wannafly Winter Camp Day1 (Div2, onsite)
Replay Dup4: 要是不挂机,再多仔细想想就好了 J确实自闭好久,一直在想正确性,最后数据错了,喵喵喵? 还是要保证充足的休息啊,中间睡了一小会儿,也不知道睡了多久,醒来他们就又过了一道 要发 ...
随机推荐
- nyoj-586-疯牛|poj-2456-Aggressive cows
http://acm.nyist.net/JudgeOnline/problem.php?pid=586 http://poj.org/problem?id=2456 解题思路:最大化最小值二分答案即 ...
- [LUOGU]P1443 马的遍历
题目描述 有一个n*m的棋盘(1< n,m<=400),在某个点上有一个马,要求你计算出马到达棋盘上任意一个点最少要走几步 输入输出格式 输入格式: 一行四个数据,棋盘的大小和马的坐标 输 ...
- centos7 中安装 mysql5.6 的过程
前提是Centos的环境是好的,并且相关的软件包已经安装好. 1.创建用户,并修改创建的数据目录的属主 [root@bogon ~]# useradd -M mysql -s /sbin/nologi ...
- Git学习——查看修改记录
查看修改结果 修改之前commit的文件,输入下面的而命令,可以查看文件的改动,输入下面命令.还可以采用git diff命令来看看具体修改了什么. 如果确认无误,添加add和提交commit文件. g ...
- PWA天气应用
https://codelabs.developers.google.com/codelabs/your-first-pwapp/#0 1.介绍 这里将使用PWA技术来构建一个天气web应用,这个ap ...
- leepcode作业解析 - 5-20
22.缺失数字 给定一个包含 0, 1, 2, ..., n 中 n 个数的序列,找出 0 .. n 中没有出现在序列中的那个数. 示例 1: 输入: [3,0,1] 输出: 2 示例 2: 输入: ...
- (原)iOS 用recursiveDescription打印View
今天要做一个搜索功能,用到UISearchBar 无奈背景太丑,就自定义了一个,首先用View私有方法打印一下searchBar的层次, 具体修改代码如下 for (UIView *view in _ ...
- Spring,Mybatis,Springmvc框架整合项目(第二部分)
一.创建数据库表 打开Navicat Premium,点击左上角连接,选择mysql 输入你的数据库用户名和密码信息,可以先点击下测试连接,如果显示连接成功,说明能连接到数据库,然后点击确定.如果 ...
- google F12
谷歌浏览器(Google Chrome)开发调试详细介绍 博客分类: 前端 浏览器chromegoogle调试开发 很多Web前台开发者都喜欢这种浏览器自带的开发者工具,这对前台设计.代码调试很大帮 ...
- mysql远程访问另一台主机数据库表,实现小表广播功能
1.打开navicat,打开任意一个连接,新建一个查询,输入命令 show engines,出现如下界面 2. 如果FEDERATED对应的Support值为NO,则找到C:\ProgramData\ ...