NOIP2016题解
D1T1:把方向和朝向异或一下,在mod n意义下+1s或-1s。
#include<cstdio>
const int N=1e5+5;
int n,m,j,k,v,s[N];
char t[N][11];
int main(){
scanf("%d%d",&n,&m);
for(int i=0;i<n;++i)
scanf("%d%s",s+i,t[i]);
while(m--){
scanf("%d%d",&j,&k);
(v+=j^s[v]?k:n-k)%=n;
}
puts(t[v]);
}
D1T2:设i的深度为d[i],点i的答案是满足s[j]在其子树中,d[s[j]]==d[i]+w[i],且lca[j]在其子树外或等于i的j的个数,加上t[j]在其子树中,d[lca[j]]*2-d[s[j]]==d[i]-w[i],且lca[j]在其子树外(s[j]在子树外)的j的个数。考虑差分链,++a[s[i]],--a[lca[j]的父亲],++b[t[j]],--b[lca[j]],那么查询子树中对应的a的和和b的和就是答案。通过dfs序,转化为查询区间中等于一个数的数的权和,那么差分询问,设查询[l,r],答案就是r处的答案减去l-1处的答案。
#include<cstdio>
const int N=3e5+5;
struct edge{
int v;edge*s;
}e[N*2];
edge*o=e,*h[N];
void ins(int u,int v){
edge s={v,h[u]};
*(h[u]=o++)=s;
}
typedef int arr[N];
arr d,p,r,c,y,l,q,z[4];
void dfs1(int u){
r[u]=1;
for(edge*i=h[u];i;i=i->s)
if(i->v^p[u]){
d[i->v]=d[p[i->v]=u]+1;
dfs1(i->v);
r[u]+=r[i->v];
if(r[c[u]]<r[i->v])
c[u]=i->v;
}
}
void dfs2(int u,int f){
static int n2;
l[u]=++n2,y[u]=f;
if(c[u])dfs2(c[u],y[u]);
for(edge*i=h[u];i;i=i->s)
if(i->v^p[u]&&i->v^c[u])
dfs2(i->v,i->v);
}
int lca(int s,int t){
while(y[s]^y[t]){
if(d[y[s]]<d[y[t]])
s^=t,t^=s,s^=t;
s=p[y[s]];
}
return d[s]<d[t]?s:t;
}
struct foo{
int z,x,y;foo*s;
}e2[N*4];
foo*o2=e2,*h2[N],*h3[N];
#define ins2(v,...){\
foo e={__VA_ARGS__,v};\
*(v=o2++)=e;\
}
struct bar{
int x,y;bar*s;
}e3[N*4];
bar*o3=e3,*h4[N],*h5[N];
#define ins3(v,...){\
bar e={__VA_ARGS__,v};\
*(v=o3++)=e;\
}
int n,m,s,t;
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<n;++i){
scanf("%d%d",&s,&t);
ins(s,t),ins(t,s);
}
dfs1(1),dfs2(1,1);
for(int i=1;i<=n;++i){
scanf("%d",&s);
int x=l[i]-1,y=x+r[i];
ins2(h2[x],i,d[i]+s,-1);
ins2(h2[y],i,d[i]+s,+1);
ins2(h3[x],i,d[i]-s,-1);
ins2(h3[y],i,d[i]-s,+1);
}
while(m--){
scanf("%d%d",&s,&t);
int i=lca(s,t),j=p[i];
int x=d[s],y=d[i]*2-x;
ins3(h4[l[s]],x,+1);
ins3(h4[l[j]],x,-1);
ins3(h5[l[t]],y,+1);
ins3(h5[l[i]],y,-1);
}
for(int i=1;i<=n;++i){
for(bar*j=h4[i];j;j=j->s)
z[0][j->x]+=j->y;
for(bar*j=h5[i];j;j=j->s)
z[3][j->x]+=j->y;
for(foo*j=h2[i];j;j=j->s)
q[j->z]+=z[0][j->x]*j->y;
for(foo*j=h3[i];j;j=j->s)
q[j->z]+=z[3][j->x]*j->y;
}
for(int i=1;i<=n;++i)
printf("%d ",q[i]);
}
D1T3:设f[i][j][2]表示前i节课,申请了j次,第i节课有没有申请的期望。floyd预处理两点间最短路。讨论所有情况,按概率加权直接转移。
#include<cstdio>
#include<cstring>
#include<algorithm>
using std::min;
const int N=2005;
int n,m,v,e,a,b,w;
int c[N],d[N],z[305][305];
double p[N],f[N][N][2];
template<class T>
void eq1(T&a,T b){a=b<a?b:a;}
int main(){
scanf("%d%d%d%d",&n,&m,&v,&e);
for(int i=1;i<=n;++i)
scanf("%d",c+i);
for(int i=1;i<=n;++i)
scanf("%d",d+i);
for(int i=1;i<=n;++i)
scanf("%lf",p+i);
memset(z,63,sizeof z);
for(int i=1;i<=v;++i)
z[i][i]=0;
while(e--){
scanf("%d%d%d",&a,&b,&w);
eq1(z[a][b],w);
eq1(z[b][a],w);
}
for(int k=1;k<=v;++k)
for(int i=1;i<=v;++i)
for(int j=1;j<=v;++j)
eq1(z[i][j],z[i][k]+z[k][j]);
for(int i=1;i<=n;++i)
for(int j=0;j<=m;++j)
f[i][j][0]=f[i][j][1]=1e18;
f[1][0][0]=f[1][1][1]=0;
for(int i=2;i<=n;++i){
f[i][0][0]=f[i-1][0][0]+z[c[i-1]][c[i]];
for(int j=1;j<=i;++j){
f[i][j][0]=min(f[i-1][j][0]+z[c[i-1]][c[i]],f[i-1][j][1]+z[c[i-1]][c[i]]*(1-p[i-1])+z[d[i-1]][c[i]]*p[i-1]);
f[i][j][1]=min(f[i-1][j-1][0]+z[c[i-1]][c[i]]*(1-p[i])+z[c[i-1]][d[i]]*p[i],f[i-1][j-1][1]+z[c[i-1]][c[i]]*(1-p[i-1])*(1-p[i])+z[d[i-1]][c[i]]*p[i-1]*(1-p[i])+z[c[i-1]][d[i]]*(1-p[i-1])*p[i]+z[d[i-1]][d[i]]*p[i-1]*p[i]);
}
}
double ans=1e18;
for(int j=0;j<=m;++j)
eq1(ans,min(f[n][j][0],f[n][j][1]));
printf("%.2f\n",ans);
}
D2T1:预处理$[\binom{i}{j}\equiv0\pmod{k}]$的二维前缀和。
#include<cstdio>
const int N=2005;
int t,p,n,m;
int c[N][N],s[N][N];
int main(){
scanf("%d%d",&t,&p);
for(int i=0;i<N;++i){
c[i][0]=1;
for(int j=1;j<=i;++j)
c[i][j]=(c[i-1][j]+c[i-1][j-1])%p;
}
for(int i=1;i<N;++i)
for(int j=1;j<N;++j){
s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1];
if(j<=i)s[i][j]+=!c[i][j];
}
while(t--){
scanf("%d%d",&n,&m);
printf("%d\n",s[n][m]);
}
}
D2T2:先从大到小排序,若q=0,考虑每次把分成的两个数压进两个队列,那么压进去的数一定不大于上次压进对应队列的数。容易验证若q!=0仍然成立。
#include<algorithm>
#include<cstdio>
#include<functional>
using namespace std;
const int M=7e6+5;
int q1[M],q2[M],q3[M];
int m,q,u,v,t;
int a1,b1,a2,b2,a3,b3;
inline int pop(){
return a1!=b1&&(a2==b2||q1[a1]>=q2[a2])&&(a3==b3||q1[a1]>=q3[a3])?q1[a1++]:a2!=b2&&(a1==b1||q2[a2]>=q1[a1])&&(a3==b3||q2[a2]>=q3[a3])?q2[a2++]:q3[a3++];
}
int main(){
scanf("%d%d%d%d%d%d",&b1,&m,&q,&u,&v,&t);
for(int i=0;i<b1;++i)
scanf("%d",q1+i);
sort(q1,q1+b1,greater<int>());
for(int i=1;i<=m;++i){
int j=pop()+(i-1)*q;
int k=1ll*j*u/v;
q2[b2++]=max(k,j-k)-i*q;
q3[b3++]=min(k,j-k)-i*q;
if(i%t==0)
printf(i==t?"%d":" %d",j);
}
puts("");
for(int i=1;i<=b1+m;++i){
int j=pop()+m*q;
if(i%t==0)
printf(i==t?"%d":" %d",j);
}
}
D2T3:先枚举两只猪,算出对应抛物线能打掉哪些猪。f[S]表示状态为S的最小步数,显然可以O(n^2)转移。考虑到每只猪都要打掉,因此只用考虑某一只没被打掉的猪和其他猪一起被打掉的情况,就可以O(n)转移了。
#include<cmath>
#include<cstdio>
#include<cstring>
#include<utility>
#define x first
#define y second
using std::pair;
typedef double real;
typedef pair<real,real>vec;
const real eps=1e-8;
int in(vec a,vec l){
return fabs(l.x*a.x*a.x+l.y*a.x-a.y)<eps;
}
const int N=18;
vec a[N];
void eq1(int&a,int b){
a=b<a?b:a;
}
int q,n,e[N][N],f[1<<N];
int main(){
scanf("%d",&q);
while(q--){
memset(e,0,sizeof e);
scanf("%d%*d",&n);
for(int i=0;i<n;++i)
scanf("%lf%lf",&a[i].x,&a[i].y);
for(int i=0;i<n;++i){
e[i][i]=1<<i;
for(int j=i+1;j<n;++j){
vec s=a[i],t=a[j];
real a1=s.x*s.x,b1=s.x,c1=s.y;
real a2=t.x*t.x,b2=t.x,c2=t.y;
real d=a1*b2-a2*b1;
if(fabs(d)>eps){
real x=(c1*b2-c2*b1)/d;
if(x<-eps){
vec l(x,(a1*c2-a2*c1)/d);
for(int k=0;k<n;++k)
e[i][j]|=in(a[k],l)<<k;
}
}
}
}
for(int i=1;i<1<<n;++i)
f[i]=n;
for(int i=0;i<1<<n;++i){
int j=__builtin_ctz(~i);
for(int k=j;k<n;++k)
eq1(f[i|e[j][k]],f[i]+1);
}
printf("%d\n",f[(1<<n)-1]);
}
}
NOIP2016题解的更多相关文章
- Noip2016题解&总结
原文放在我的uoj博客上,既然新开了blog,那就移过来了 玩具谜题(toy) 送分题.没有什么好说的. 直接按照题目的要求模拟即可. 标准的noip式day1T1. #include<cstd ...
- [NOIP补坑计划]NOIP2016 题解&做题心得
感觉16年好难啊QAQ,两天的T2T3是不是都放反了啊…… 场上预计得分:100+80+100+100+65+100=545(省一分数线280) ps:loj没有部分分,部分分见洛咕 题解: D1T1 ...
- noip2016题解汇总
[uoj#260]玩具谜题 传送门 http://uoj.ac/problem/260 分析 模拟. int n,m; int dir[N]; char nam[N][L]; int a[M],s[M ...
- NOIP2016天天爱跑步 题解报告【lca+树上统计(桶)】
题目描述 小c同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.«天天爱跑步»是一个养成类游戏,需要玩家每天按时上线,完成打卡任务. 这个游戏的地图可以看作一一棵包含 nn个 ...
- 【题解】NOIP2016提高组 复赛
[题解]NOIP2016提高组 复赛 传送门: 玩具谜题 \(\text{[P1563]}\) 天天爱跑步 \(\text{[P1600]}\) 换教室 \(\text{[P1850]}\) 组合数问 ...
- 【题解】NOIP2016 提高组 简要题解
[题解]NOIP2016 提高组 简要题解 玩具迷题(送分) 用异或实现 //@winlere #include<iostream> #include<cstdio> #inc ...
- 「NOIP2016」天天爱跑步 题解
(声明:图片来源于网络) 「NOIP2016」天天爱跑步 题解 题目TP门 题目 题目描述 小c同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.<天天爱跑步>是 ...
- noip2016十连测题解
以下代码为了阅读方便,省去以下头文件: #include <iostream> #include <stdio.h> #include <math.h> #incl ...
- [题解]noip2016普及组题解和心得
[前言] 感觉稍微有些滑稽吧,毕竟每次练的题都是提高组难度的,结果最后的主要任务是普及组抱一个一等奖回来.至于我的分数嘛..还是在你看完题解后写在[后记]里面.废话不多说,开始题解. 第一题可以说的内 ...
随机推荐
- Web Mercator Non-Conformal, Non-Mercator
public static void XYtoGL(Coordinate coordinate) { double R = 6378137; coordinate.x = coordinate.x / ...
- 从 HTTP 到 HTTPS - 什么是 HTTPS
这篇文章首发于我的个人网站:听说 - https://tasaid.com/,建议在我的个人网站阅读,拥有更好的阅读体验. 这篇文章与 博客园 和 Segmentfault 共享. 前端开发QQ群:3 ...
- 使用WebRTC搭建前端视频聊天室——数据通道篇
本文翻译自WebRTC data channels 在两个浏览器中,为聊天.游戏.或是文件传输等需求发送信息是十分复杂的.通常情况下,我们需要建立一台服务器来转发数据,当然规模比较大的情况下,会扩展成 ...
- 用NSCalendar和UICollectionView自定义日历,并实现签到显示
前一段时间因为工作需要实现了一个可以签到的日历,来记录一下实现的思路 效果如图: 这里的基本需求是: 1,显示用户某个月的签到情况,已经签到的日子打个圈,没有签到且在某个时间范围内的可以签到,其他 ...
- React Native 之 组件化开发
前言 学习本系列内容需要具备一定 HTML 开发基础,没有基础的朋友可以先转至 HTML快速入门(一) 学习 本人接触 React Native 时间并不是特别长,所以对其中的内容和性质了解可能会有所 ...
- 简历生成平台项目开发-STEP3第一次项目例会探讨
时间:2016.7.13周三7点半 地点:图书馆 讨论主题:项目需求和功能分析.第一次任务分配 内容:按照之前的讨论,我们认为简历生成功能,不仅要适应学生求职的需求,更多的是要在格式和内容上满足HR的 ...
- (八)map,filter,flatMap算子-Java&Python版Spark
map,filter,flatMap算子 视频教程: 1.优酷 2.YouTube 1.map map是将源JavaRDD的一个一个元素的传入call方法,并经过算法后一个一个的返回从而生成一个新的J ...
- 认识 EXT2 文件系统
认识ext文件系统 硬盘组成与分割 文件系统特性 Linux 的 EXT2 文件系统(inode) 与目录树的关系 EXT2/EXT3 文件的存取与日志式文件系统的功能 Linux 文件系统的运行 挂 ...
- monkeyrunner之控件ID不存在或重复
我们在用monkeyrunner进行Android自动化时,通过获取坐标点或控件ID进行一系列操作.由于使用坐标点时,屏幕分辨率一旦更改,则代码中用到坐标的地方都要修改,这样导致代码的复用率较低.因此 ...
- 常用的14种HTTP状态码速查手册
分类 1xx \> Information(信息) // 接收的请求正在处理 2xx \> Success(成功) // 请求正常处理完毕 3xx \> Redirection(重定 ...