2019ICPC陕西邀请赛复盘
题目链接:The 2019 ACM-ICPC China Shannxi Provincial Programming Contest
A:签到,按花费时间从小到大排个序
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=;
int a[N];
int main()
{
int n,t;
while(~scanf("%d%d",&n,&t))
{
for(int i=;i<=n;i++)
scanf("%d",&a[i]);
sort(a+,a++n);
int ans=;
for(int i=;i<=n;i++)
{
if(t>=a[i])
{
t-=a[i];
ans++;
}
else
break;
}
printf("%d\n",ans);
}
return ;
}
日常签到
L:签到,因为序列里的数都不一样,所以答案只跟n有关,两次同样的操作的话序列就换回来了,所以肯定是两个操作交替进行,然后照着题意打表找规律,注意1和3要特判
#include<cstdio>
int main()
{
int n,x;
while(~scanf("%d",&n))
{
for(int i=;i<n;i++)
scanf("%d",&x);
if(n==)
printf("1\n");
else if(n==)
printf("6\n");
else if(n%==)
printf("4\n");
else if(n%==)
printf("%d\n",*n);
else if(n%==)
printf("%d\n",n);
else
printf("12\n");
}
return ;
}
日常打表
M:二分最短路,首先题意是,给出了一个星系里每个星球的路线图,然后有一艘飞船,它有三个属性,等级和最长的航行距离以及航行次数,初始都是0,然后可以升级,每升一级,花费费用c,最长航行距离增长d,航行次数增加e。如果某条路线的长度大于飞船的最长的航行距离,那么飞船不能走这条路线,并且每走一过一条路就消耗1的航行次数,当航行次数为0,飞船也不能走了。问从1号星球到n号星球的最小费用是多少。
我们就二分升级的次数,那么能走的路线就是长度小于等于次数*d的,在这个限制以每条路线距离为1,求一个1号星球到n号星球的最短距离,判断一下这个距离是不是小于等于次数*e。
#include<cstdio>
#include<queue>
using namespace std;
typedef long long ll;
const int N=,inf=;
struct Side{
int v,ne,w;
Side(){}
Side(int v,int w):v(v),w(w){}
bool operator< (const Side &s1)const{
return w>s1.w;
}
}S[N<<];
int sn,head[N],dis[N],vis[N];
void init(int n)
{
sn=;
for(int i=;i<=n;i++)
head[i]=-;
}
void add(int u,int v,int w)
{
S[sn].v=v;
S[sn].w=w;
S[sn].ne=head[u];
head[u]=sn++;
}
bool dijk(int n,ll lim,ll num)
{
priority_queue<Side> q;
for(int i=;i<=n;i++)
{
vis[i]=;
dis[i]=inf;
}
dis[]=;
q.push(Side(,));
int u,v;
while(!q.empty())
{
u=q.top().v;
q.pop();
if(u==n)
break;
if(vis[u])
continue;
vis[u]=;
for(int i=head[u];~i;i=S[i].ne)
{
v=S[i].v;
if(S[i].w<=lim&&dis[v]>dis[u]+)
{
dis[v]=dis[u]+;
q.push(Side(v,dis[v]));
}
}
}
return dis[n]<=num;
}
int main()
{
int n,m,c,d,e,u,v,w;
while(~scanf("%d%d",&n,&m))
{
init(n);
scanf("%d%d%d",&c,&d,&e);
while(m--)
{
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);
add(v,u,w);
}
int l=,r=1e5,mid,ans=-;
while(l<=r)
{
mid=(l+r)>>;
if(dijk(n,1ll*mid*d,1ll*mid*e))
r=mid-,ans=mid;
else
l=mid+;
}
if(ans==-)
printf("-1\n");
else
printf("%lld\n",1ll*ans*c);
}
return ;
}
日常二分
C:计算几何。根据题意大概就是下面这个美美的图。
蓝色的线以下除了圆弧外都不能走,所以O2肯定是先走4分之一圆弧,走到l或者r点处,然后如果目标点是A或者C的话,接下来肯定就是l与A的两点之间的距离,或者r与C两点之间的距离,而如果目标点是B点的话,那么就是得先求出两个切点p1,p2了,然后l或r走到p1或p2,最后再是p1或p2走到B的最短距离,求切点就是模板了。
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
const double pi=acos(-1.0);
struct Point{
double x,y;
Point(){}
Point(double x,double y):x(x),y(y){}
}pr,pa;
double r;
double dis(Point p1,Point p2){
return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
}
void cutp(Point &p1,Point &p2)//求圆外一点和圆的两个切点
{
Point E,F,G,H;
E.x=pa.x-pr.x;
E.y=pa.y-pr.y;
double temp=r/dis(E,Point(,));
F.x=E.x*temp;
F.y=E.y*temp;
double a=acos(temp),b=-acos(temp);
G.x=F.x*cos(a)-F.y*sin(a);
G.y=F.x*sin(a)+F.y*cos(a);
H.x=F.x*cos(b)-F.y*sin(b);
H.y=F.x*sin(b)+F.y*cos(b);
p1.x=G.x+pr.x;
p1.y=G.y+pr.y;
p2.x=H.x+pr.x;
p2.y=H.y+pr.y;
return ;
}
double Larc(Point p1,Point p2)//求圆上两点的弧长
{
double d=dis(p1,p2);
double a=acos((r*r+r*r-d*d)*0.5/r/r);
return a*r;
}
double solve()
{
Point p1,p2;
Point rl(pr.x-r,pr.y),rr(pr.x+r,pr.y);
if(pa.x<rl.x)
return dis(pa,rl);
else if(pa.x>rr.x)
return dis(pa,rr);
else
{
cutp(p1,p2);
double dis1=dis(pa,p1),dis2=dis(pa,p2);
return min(min(Larc(rl,p1),Larc(rr,p1))+dis1,min(Larc(rl,p2),Larc(rr,p2))+dis2);
}
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%lf%lf%lf%lf%lf",&pr.x,&pr.y,&r,&pa.x,&pa.y);
printf("%.4f\n",pi*r*0.5+solve());
}
return ;
}
日常模板
D:一个很神奇的背包,坤神教的。首先物品中有对立的存在,所以我们把所有对立的物品分成a类和b类,这样要a[i]的话,b[i]就是另一个人的,对于每一组a,b(假设a>=b),那么两人都有b这部分,就看a-b这部分差距分给谁。那么dp[i],就代表Miku能不能得到分到i的差距,把差距视为体积和价值,要或不要就是背包问题了。最后要差距尽可能的小,那就是从一半的差距开始分,找到第一个可以分到的差距。
#include<cstdio>
#include<cstdlib>
#include<algorithm>
using namespace std;
const int N=;
struct Side{
int v,ne;
}S[N<<];
int sn,cnt,head[N],a[N],b[N],c[N],d[N],vis[N];
bool dp[];
void init(int n)
{
sn=cnt=;
for(int i=;i<=n;i++)
{
vis[i]=;
head[i]=-;
a[i]=b[i]=;
}
}
void add(int u,int v)
{
S[sn].v=v;
S[sn].ne=head[u];
head[u]=sn++;
}
void dfs(int u,int op)
{
vis[u]=op;
for(int i=head[u];~i;i=S[i].ne)
if(!vis[S[i].v])
dfs(S[i].v,op*-);
if(op>)
a[cnt]+=c[u];
else
b[cnt]+=c[u];
}
int main()
{
int t,n,m,u,v;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
init(n);
for(int i=;i<=n;i++)
scanf("%d",&c[i]);
while(m--)
{
scanf("%d%d",&u,&v);
add(u,v);
add(v,u);
}
for(int i=;i<=n;i++)
if(!vis[i])
{
cnt++;
dfs(i,);
}//先把物品分类
int sumd=,sumi=;//sumd保持的是总的差距,差距除100离散化
//sumi就是先保持小的总和
for(int i=;i<=cnt;i++)
{
d[i]=abs(a[i]-b[i])/;
sumd+=d[i];
sumi+=min(a[i],b[i]);
}
for(int i=;i<=sumd;i++)
dp[i]=false;
dp[]=true;
//01背包
for(int i=;i<=cnt;i++)
for(int j=sumd;j>=d[i];j--)
dp[j]|=dp[j-d[i]];
for(int i=(sumd+)/;i<=sumd;i++)
if(dp[i])
{
printf("%d\n",i*+sumi);
break;
}
}
return ;
}
日常背包
J:树形dp,题目问的是异或和为0的路径包含在多少条路径之中的和,在下图中如果2到5这条路径的异或和为0,那么它就包含在3*3=9条路径中,也就是size[2]*size[5],size是子树大小。
所以答案的统计可以分成两种,第一种是对于不在一条链上的,贡献的答案就是它们的子树大小的乘积,而第二种就是在同一条链上的就是父代节点上面的部分与子代节点子树部分的乘积。
我们维护一个从根节点到这个节点的异或和,假设为w,开个map,mmp[w]就记录从根节点到这个节点异或和为w的所有子树大小之和。然后,对于一个节点来说,dfs是搜索完子树之和再操作它,所以这个mmp[w]可能就包含了它子树的贡献值,这部分对第一种情况没有贡献,所以我们记录下dfs到它时的mmp,这就是不包含它子树的,然后对于第二种情况,在进入它子树的每一条链前我们就记录下mmp[w],在搜索完这条链后,新的mmp[w]与旧的差值就是它子代节点的贡献值。
#include<cstdio>
#include<map>
using namespace std;
typedef long long ll;
const int N=,mod=;
struct Side{
ll w;
int v,ne;
}S[N];
int n,sn,head[N],size[N];
ll ans;
map<ll,ll> mmp;
void init()
{
sn=ans=;
mmp.clear();
for(int i=;i<=n;i++)
{
size[i]=;
head[i]=-;
}
}
void add(int u,int v,ll w)
{
S[sn].w=w;
S[sn].v=v;
S[sn].ne=head[u];
head[u]=sn++;
}
void dfs(int u,ll w)
{
ll num1=mmp[w],num2;
for(int i=head[u],v;~i;i=S[i].ne)
{
v=S[i].v;
num2=mmp[w];
dfs(v,w^S[i].w);
size[u]+=size[v];
ans+=1ll*(n-size[v])*(mmp[w]-num2);//第二种情况与它子树的链的
if(ans>=mod)
ans%=mod;
}
ans+=1ll*num1*size[u];//第一种情况,与其他链的
if(ans>=mod)
ans%=mod;
mmp[w]+=size[u];
if(mmp[w]>=mod)
mmp[w]%=mod;
}
int main()
{
int f;
ll w;
while(~scanf("%d",&n))
{
init();
for(int i=;i<=n;i++)
{
scanf("%d%lld",&f,&w);
add(f,i,w);
}
dfs(,0ll);
printf("%lld\n",ans);
}
return ;
}
日常dp
最后E,坤神已经补出来了,等我补了再更。
2019ICPC陕西邀请赛复盘的更多相关文章
- 计蒜客 39272.Tree-树链剖分(点权)+带修改区间异或和 (The 2019 ACM-ICPC China Shannxi Provincial Programming Contest E.) 2019ICPC西安邀请赛现场赛重现赛
Tree Ming and Hong are playing a simple game called nim game. They have nn piles of stones numbered ...
- 一类SG函数递推性质的深入分析——2018ACM陕西邀请赛H题
题目描述 定义一种有根二叉树\(T(n)\)如下: (1)\(T(1)\)是一条长度为\(p\)的链: (2)\(T(2)\)是一条长度为\(q\)的链: (3)\(T(i)\)是一棵二叉树,它的左子 ...
- 树链剖分的一种妙用与一类树链修改单点查询问题的时间复杂度优化——2018ACM陕西邀请赛J题
题目描述 有一棵树,每个结点有一个灯(初始均是关着的).每个灯能对该位置和相邻结点贡献1的亮度.现有两种操作: (1)将一条链上的灯状态翻转,开变关.关变开: (2)查询一个结点的亮度. 数据规模:\ ...
- HDU 4847 陕西邀请赛A(水)
HDU 4847 Wow! Such Doge! pid=4847" style="">题目链接 题意:给定文本,求有几个doge,不区分大写和小写 思路:水题.直 ...
- 2019ICPC南昌邀请赛网络赛 I. Max answer (单调栈+线段树/笛卡尔树)
题目链接 题意:求一个序列的最大的(区间最小值*区间和) 线段树做法:用单调栈求出每个数两边比它大的左右边界,然后用线段树求出每段区间的和sum.最小前缀lsum.最小后缀rsum,枚举每个数a[i] ...
- 2019ICPC西安邀请赛 - B. Product - 数论
打印的时候麻烦把:https://blog.csdn.net/skywalkert/article/details/50500009这个打印下来. 求\(\prod\limits_{i=1}^{n} ...
- 2019ICPC西安邀请赛(计蒜客复现赛)总结
开始时因为吃饭晚了一刻钟,然后打开比赛.看了眼榜单A题已经过了二十来个队伍了,宝儿就去做A. 传师说最后一题看题目像最短路,于是我就去看M了,宝儿做完之后也来陪我看.M一开始看到时以为是像 POJ ...
- HDU 4849 Wow! Such City!陕西邀请赛C(最短路)
HDU 4849 Wow! Such City! 题目链接 题意:依照题目中的公式构造出临接矩阵后.求出1到2 - n最短路%M的最小值 思路:就依据题目中方法构造矩阵,然后写一个dijkstra,利 ...
- 计蒜客 39280.Travel-二分+最短路dijkstra-二分过程中保存结果,因为二分完最后的不一定是结果 (The 2019 ACM-ICPC China Shannxi Provincial Programming Contest M.) 2019ICPC西安邀请赛现场赛重现赛
Travel There are nn planets in the MOT galaxy, and each planet has a unique number from 1 \sim n1∼n. ...
随机推荐
- 第十一章 ZYNQ-MIZ702 DDR3 PS读写操作方案
本编文章的目的主要用简明的方法在纯PS里对DDR3进行读写. 本文所使用的开发板是Miz702 PC 开发环境版本:Vivado 2015.4 Xilinx SDK 2015.4 11.0本章难度 ...
- 【Trie】L 语言
[题目链接]: https://loj.ac/problem/10053 [题意]: 给出n个模式串.请问文本串是由多少个模式串组成的. [题解]: 当我学完AC自动机后,发现这个题目也太简单了吧. ...
- js实现div转图片并保存
最近工作中遇到的需求,将div转成图片并保存. 1.准备需要用到的js插件jquery-1.8.2.js,html2canvas.min.js(将div转换为canvas),bluebird.js(用 ...
- __imp__SetupDiDestroyDeviceInfoList
error LINK2019 unresolved external symbol __imp__SetupDiDestroyDeviceInfoList 分类: 转载文章2012-11-02 15: ...
- [转载]clip gradient抑制梯度爆炸
[转载]clip gradient抑制梯度爆炸 来源:https://blog.csdn.net/u010814042/article/details/76154391 1.梯度爆炸的影响 在一个只有 ...
- Linux学习(四)-Linux常用命令
1.运行级别类 1.1运行级别说明: 0:关机 1:单用户[可用于找回丢失密码] 2:多用户状态没有网络服务 3:多用户状态有网络服务 4:系统未使用保留给用户 5:图形界面 6:系统重启 常用运行级 ...
- property配置
之前把设备历史数据存储的时间周期存储在了数据库中,因为以下一些原因,我打算改写到property配置文件中 1.这个周期时间的配置没有单独放一个tabel中,导致现在设备类型越来越多,每次添加或者修改 ...
- Centos7.7安装swoole
系统版本:centos 7.7(查看系统版本:cat /etc/redhat-release) 执行命令安装swoole: yum update -y && yum remove ph ...
- LEANGOO成员
转自:https://www.leangoo.com/leangoo_guide/leangoo_guide_member.html 1. 看板成员及权限 一个看板上的最大成员限制为200个. 看板的 ...
- DICOM文件修改方法
/// <summary> /// 读取dicom文件 /// </summary> /// <param name="srcdirectory"&g ...