NOIP2016总结
Day1:
T1:模拟;
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<set>
#include<map>
#include<queue>
#include<algorithm>
#include<iomanip>
using namespace std;
#define FILE "toy"
#define up(i,j,n) for(int i=(j);i<=(n);i++)
#define pii pair<int,int>
#define LL long long
namespace IO{
char buf[<<],*fs,*ft;
int gc(){return (fs==ft&&(ft=(fs=buf)+fread(buf,,<<,stdin),fs==ft))?-:*fs++;}
int read(){
int ch=gc(),f=,x=;
while(ch<''||ch>''){if(ch=='-')f=;ch=gc();}
while(ch>=''&&ch<=''){x=(x<<)+(x<<)+ch-'';ch=gc();}
return f?-x:x;
}
}using namespace IO;
const int maxn=;
int n,m;
int a[maxn];
char s[maxn][];
int main(){
freopen(FILE".in","r",stdin);
freopen(FILE".out","w",stdout);
scanf("%d%d",&n,&m);
up(i,,n-)scanf("%d %s",&a[i],s[i]);
int x,y,now=;
up(i,,m){
scanf("%d%d",&x,&y);
if(x==a[now])now=(now-y+n)%n;
else now=(now+y)%n;
}
printf("%s",s[now]);
return ;
}
T2:
这次noip2016最难的题?
考场上只急着打暴力了,没有好好思考;
实际上想了之后还是很简单的;
这题的关键是理清思路,题目上的特点是 若一条路径已走的时间若与当前节点的值相等,这一点的答案加1;
最暴力的思路当然是dfs Q遍,先判断这个点是否在这条路径上,然后判断已走的距离是不是等于当前点的权值,都符合的话ans++;
如何化简条件?
我们可以发现当若有一条从x->y的路径是一条链,且dep[x]<dep[y],则若dep[i]-dep[x]=v[i],则该点ans++;
这可以变形成dep[i]-v[i]=dep[x],左边只与点i自身有关;
经过了这样的转化,我们发现可以这样做,将一个路径拆成从x->lca和lca->y两个链,然后可以仿照上面的方法,用dep与v[i]的关系做。
但做到了这一步仍然没什么卵用;
我们是否可以把目光转移,从看一条路径到看每个点?
对每个点而言,我们需要计算的是,它自身dep[i]±v[i]正好匹配经过它的路径所要求的的值的路径的数目;
这很绕,实际上对路径只有两个要求,第一个是经过它,第二个是路径与这个点可以匹配;
怎么维护?
第一个,维护只经过它的路径的值的集合;
第二个,在集合中快速找到符合要求的值的数目;
满足这两个要求,第一个可以用离线的方法维护,第二个可以在dfs的途中顺便维护一个桶,这个桶里存的就是经过它的路径的值的集合,然后可以O(1)查询;
这里面还有一个地方需要注意,每次桶从一颗子树出来的时候会带着这颗子树的信息,再进入另一个桶的时候会出现问题,解决方案是作差,先记录一下当前的ans值,待遍历完所有子树,再记录一下当前的ans,两个的差值即为所求;
在大佬眼里就是道水题...
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<set>
#include<map>
#include<queue>
#include<algorithm>
#include<iomanip>
#include<queue>
using namespace std;
#define FILE "dealing"
#define up(i,j,n) for(int i=(j);i<=(n);i++)
#define pii pair<int,int>
#define LL long long
namespace IO{
char buf[<<],*fs,*ft;
int gc(){return (fs==ft&&(ft=(fs=buf)+fread(buf,,<<,stdin),fs==ft))?-:*fs++;}
int read(){
int ch=gc(),f=,x=;
while(ch<''||ch>''){if(ch=='-')f=;ch=gc();}
while(ch>=''&&ch<=''){x=(x<<)+(x<<)+ch-'';ch=gc();}
return f?-x:x;
}
}using namespace IO;
const int maxn=;
int n,m;
struct node{
int y,next,v;
}e[maxn],u[maxn],v[maxn],q[maxn];
int headu[maxn],headv[maxn],headq[maxn],lenu,lenv,lenq;
int linkk[maxn],len=;
int s[maxn],t[maxn],w[maxn];
inline void insert(int x,int y,node* e,int* linkk,int& len,int v){e[++len].y=y;e[len].v=v;e[len].next=linkk[x];linkk[x]=len;}
int top[maxn],siz[maxn],son[maxn],fa[maxn],dep[maxn],Lca[maxn],dfs_clock=;
int f[maxn],flag[maxn];
int getf(int x){return x==f[x]?x:f[x]=getf(f[x]);}
int pre[maxn],low[maxn],id[maxn];
void tarjan(int x){
siz[x]=;
pre[x]=++dfs_clock;
id[dfs_clock]=x;
flag[x]=;
for(int i=linkk[x];i;i=e[i].next){
if(e[i].y==fa[x])continue;
fa[e[i].y]=x;
dep[e[i].y]=dep[x]+;
tarjan(e[i].y);
}
for(int i=headq[x];i;i=q[i].next){
if(Lca[q[i].v])continue;
if(flag[q[i].y]==)Lca[q[i].v]=q[i].y;
else if(flag[q[i].y]==)Lca[q[i].v]=getf(q[i].y);
}
f[x]=fa[x];
flag[x]=;
low[x]=++dfs_clock;
id[dfs_clock]=x;
}
void init(){
n=read(),m=read();
int x,y;
up(i,,n-){x=read(),y=read();insert(x,y,e,linkk,len,);insert(y,x,e,linkk,len,);}
up(i,,n)w[i]=read();
up(i,,m){
s[i]=read(),t[i]=read();
insert(s[i],t[i],q,headq,lenq,i);
insert(t[i],s[i],q,headq,lenq,i);
}
up(i,,n)f[i]=i;
tarjan();
}
inline void make_tag(int s,int t,int st,bool flag){
if(flag){
insert(s,st,u,headu,lenu,);
insert(t,st,u,headu,lenu,-);
}
else {
insert(s,st,v,headv,lenv,);
insert(t,st,v,headv,lenv,-);
}
}
int ans[maxn];
int cnt1[maxn<<],cnt2[maxn<<];
int l[maxn];
void slove(){
up(i,,m){
if(Lca[i]==s[i])make_tag(fa[s[i]],t[i],dep[s[i]],);
else if(Lca[i]==t[i])make_tag(s[i],fa[t[i]],dep[s[i]],);
else {
make_tag(s[i],fa[Lca[i]],dep[s[i]],);
make_tag(Lca[i],t[i],*dep[Lca[i]]-dep[s[i]],);
}
}
memset(flag,,sizeof(flag));
int x;
for(int i=;i<=dfs_clock;i++){
x=id[i];
if(flag[x]){
for(int i=headu[x];i;i=u[i].next){
if(u[i].v==-)cnt1[u[i].y+maxn]--;
else cnt1[u[i].y+maxn]++;
}
for(int i=headv[x];i;i=v[i].next){
if(v[i].v==)cnt2[v[i].y+maxn]--;
else cnt2[v[i].y+maxn]++;
}
ans[x]=cnt1[dep[x]+w[x]+maxn]+cnt2[dep[x]-w[x]+maxn]-l[x];
}
else {
l[x]=cnt1[dep[x]+w[x]+maxn]+cnt2[dep[x]-w[x]+maxn];
flag[x]=;
}
}
up(i,,n)printf("%d%c",ans[i],i==n?'\n':' ');
}
int main(){
freopen(FILE".in","r",stdin);
freopen(FILE".out","w",stdout);
init();
slove();
return ;
}
顺便进行了一下求lca的速度测试:
只求LCA的话,树链剖分最快,tarjan次之,倍增最慢(经常被卡);
还需要一些附加信息的话,tarjan无法处理,树链剖分效率很好,倍增效率太低;
代码长度上,树链剖分最长,lca次之,tarjan最短;
如果考场上只求lca的话,建议tarjan,很好写;
T3:
无力吐槽,这题让一心一意备考noip的人怎么受得了;
概率dp;
把概率扒下来其实就是一背包动规;
具体的还是自己去体会(看代码)......
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<set>
#include<map>
#include<queue>
#include<algorithm>
#include<iomanip>
#include<queue>
using namespace std;
#define FILE "dealing"
#define up(i,j,n) for(int i=(j);i<=(n);i++)
#define pii pair<int,int>
#define LL long long
#define db double
namespace IO{
char buf[<<],*fs,*ft;
int gc(){return (fs==ft&&(ft=(fs=buf)+fread(buf,,<<,stdin),fs==ft))?-:*fs++;}
int read(){
int ch=gc(),f=,x=;
while(ch<''||ch>''){if(ch=='-')f=;ch=gc();}
while(ch>=''&&ch<=''){x=(x<<)+(x<<)+ch-'';ch=gc();}
return f?-x:x;
}
}using namespace IO;
const int maxn=;
const db inf=100000000.0;
int n,m,v,e,a[maxn],b[maxn];
db k[maxn];
int d[maxn][maxn];
void init(){
scanf("%d%d%d%d",&n,&m,&v,&e);
memset(d,,sizeof(d));
up(i,,v)d[i][i]=;
up(i,,n)scanf("%d",&a[i]);
up(i,,n)scanf("%d",&b[i]);
up(i,,n)scanf("%lf",&k[i]);
int x,y,vv;
up(i,,e){
scanf("%d%d%d",&x,&y,&vv);
if(d[x][y]>vv)d[x][y]=d[y][x]=vv;
}
up(g,,v)up(i,,v)up(j,,v)if(d[i][g]+d[g][j]<d[i][j])d[i][j]=d[i][g]+d[g][j];
}
db f[][][];
void slove(){
up(i,,n)up(j,,m)f[i][j][]=f[i][j][]=inf;
f[][][]=f[][][]=;
db duu,duv,dvu,dvv,ans=inf;
up(i,,n)for(int j=;j<=i&&j<=m;j++){
duu=d[a[i-]][a[i]],duv=d[a[i-]][b[i]],dvu=d[b[i-]][a[i]],dvv=d[b[i-]][b[i]];
if(j!=i)f[i][j][]=min(f[i-][j][]+duu*(-k[i-])+dvu*k[i-],duu+f[i-][j][]);
if(j)f[i][j][]=min(f[i-][j-][]+duu*(-k[i-])*(-k[i])+duv*(-k[i-])*k[i]+dvv*k[i]*k[i-]+dvu*k[i-]*(-k[i]),f[i-][j-][]+duv*k[i]+duu*(-k[i]));
}
for(int i=;i<=m;i++)ans=min(ans,min(f[n][i][],f[n][i][]));
printf("%.2lf\n",ans);
}
int main(){
freopen(FILE".in","r",stdin);
freopen(FILE".out","w",stdout);
init();
slove();
return ;
}
Day2:
T1:
组合数,考场脑子一抽写了二维树状数组,但实际也没什么问题(实际这题的二维动规是有一定的风险的,有人因此挂了);
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<set>
#include<map>
#include<queue>
#include<algorithm>
#include<iomanip>
using namespace std;
#define FILE "problem"
#define up(i,j,n) for(int i=(j);i<=(n);i++)
#define pii pair<int,int>
#define LL long long
namespace IO{
char buf[<<],*fs,*ft;
int gc(){return (fs==ft&&(ft=(fs=buf)+fread(buf,,<<,stdin),fs==ft))?-:*fs++;}
int read(){
int ch=gc(),f=,x=;
while(ch<''||ch>''){if(ch=='-')f=;ch=gc();}
while(ch>=''&&ch<=''){x=(x<<)+(x<<)+ch-'';ch=gc();}
return f?-x:x;
}
}using namespace IO;
const int maxn=,N=;
int c[maxn][maxn];
int sum[maxn][maxn];
int T,k,n,m;
int main(){
//freopen(FILE".in","r",stdin);
//freopen(FILE".out","w",stdout);
T=read(),k=read();
c[][]=;
up(i,,N){
c[i][]=;
up(j,,i){
c[i][j]=(c[i-][j-]+c[i-][j])%k;
sum[i][j]=sum[i-][j]+sum[i][j-]-sum[i-][j-]+(c[i][j]==?:);
}
up(j,i+,N)sum[i][j]=sum[i-][j]+sum[i][j-]-sum[i-][j-];
}
while(T--){
n=read(),m=read();
if(m>n)m=n;
printf("%d\n",sum[n][m]);
}
return ;
}
T2:
数学题目,需要证一下单调性(求个导如何?)
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<set>
#include<map>
#include<queue>
#include<algorithm>
#include<iomanip>
using namespace std;
#define FILE "earthworm"
#define up(i,j,n) for(int i=(j);i<=(n);i++)
#define pii pair<int,int>
#define LL long long
namespace IO{
char buf[<<],*fs,*ft;
int gc(){return (fs==ft&&(ft=(fs=buf)+fread(buf,,<<,stdin),fs==ft))?-:*fs++;}
int read(){
int ch=gc(),f=,x=;
while(ch<''||ch>''){if(ch=='-')f=;ch=gc();}
while(ch>=''&&ch<=''){x=(x<<)+(x<<)+ch-'';ch=gc();}
return f?-x:x;
}
}using namespace IO;
const int maxn=;
const double E=0.0000001;
int a[maxn],b[maxn],c[maxn];
int ha,hb,hc,tb=,tc=;
int n,m,u,v,t,q,d;
LL pop(){
int L;
if(ha&&(a[ha]>=b[tb]||tb>hb)&&(a[ha]>=c[tc]||tc>hc))L=a[ha],ha--;
else if(tb<=hb&&(b[tb]>=a[ha]||!ha)&&(b[tb]>=c[tc]||tc>hc))L=b[tb],tb++;
else L=c[tc],tc++;
return L;
}
int main(){
n=read(),m=read(),q=read(),u=read(),v=read(),t=read();
up(i,,n)a[i]=read();
sort(a+,a+n+);
ha=n;
LL L,top=;
up(i,,m){
L=pop()+d;
d+=q;
if(top*t==i){printf("%lld ",L);top++;}
b[++hb]=(int)(L*u/v)-d;
c[++hc]=L-b[hb]-*d;
}
cout<<endl;
top=;
up(i,,m+n){
L=pop();
if(t*top==i){printf("%lld ",L+d);top++;}
}
return ;
}
T3:
惭愧惭愧,考场不假思索,先打暴力......
后改记忆化,本质上都是状压dp;
吐槽的是,我同学写正解都被卡了一个n,而我写dfs,没有被卡掉......
实质上dfs会避免访问很多不可能出现的状态,所以效率比较高;
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<set>
#include<map>
#include<queue>
#include<algorithm>
#include<iomanip>
using namespace std;
#define FILE "angrybirds"
#define up(i,j,n) for(int i=(j);i<=(n);i++)
#define pii pair<int,int>
#define LL long long
#define pdd pair<double,double>
namespace IO{
char buf[<<],*fs,*ft;
int gc(){return (fs==ft&&(ft=(fs=buf)+fread(buf,,<<,stdin),fs==ft))?-:*fs++;}
int read(){
int ch=gc(),f=,x=;
while(ch<''||ch>''){if(ch=='-')f=;ch=gc();}
while(ch>=''&&ch<=''){x=(x<<)+(x<<)+ch-'';ch=gc();}
return f?-x:x;
}
}using namespace IO;
inline bool chkmin(int &a,int b){return a>b?a=b,true:false;}
inline bool chkmax(int &a,int b){return a<b?a=b,true:false;}
const int maxn=,N=;
const double E=0.00000001;
int T,n,m;
int ans;
double x[maxn],y[maxn];
inline bool c(double x,double y){return abs(x-y)<=E;}
inline pdd slove(double q,double w,double e,double r){
pdd dui;
if(c(q,e))return make_pair(,);
dui.first=(w*e-q*r)/(q*e*(q-e));
if(dui.first+E>=)return make_pair(,);
dui.second=(w*e-dui.first*q*q*e)/(q*e);
return dui;
}
int f[];
int dfs(int top,int vis){
if(f[vis]!=-)return f[vis];
if(top==n+)return f[vis]=;
if((<<top-)&vis)return f[vis]=dfs(top+,vis);
pdd p;
f[vis]=n;
int q=vis;
up(i,top+,n){
vis=q;
if(!((<<i-)&vis)){
p=slove(x[top],y[top],x[i],y[i]);
if(!p.first)continue;
vis=vis^(<<top-);
vis=vis^(<<i-);
up(j,top+,n){
if(vis&(<<j-))continue;
if(c(p.first*x[j]*x[j]+p.second*x[j],y[j]))vis=vis^(<<j-);
}
chkmin(f[q],dfs(top+,vis)+);
}
}
vis=q;
chkmin(f[vis],dfs(top+,vis^(<<top-))+);
return f[vis];
}
int main(){
//freopen(FILE".in","r",stdin);
//freopen(FILE".out","w",stdout);
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&m);
up(i,,n)scanf("%lf%lf",&x[i],&y[i]);
if(!m||m==)ans=n;
if(m==)ans=(n%)?(n/+):(n/+);
memset(f,-,sizeof(f));
cout<<dfs(,)<<endl;
}
return ;
}
NOIP2016总结的更多相关文章
- NOIp2016 Day1&Day2 解题报告
Day1 T1 toy 本题考查你会不会编程. //toy //by Cydiater //2016.11.19 #include <iostream> #include <cstd ...
- NOIp2016 游记
DAY -2 不要问我为什么现在就开了一篇博客. 本来想起个NOIp2016爆零记或者NOIp2016退役记之类的,但是感觉现在不能乱立flag了.所以就叫游记算了. 前几场模拟赛崩了一场又一场,RP ...
- [Noip2016]蚯蚓 D2 T2 队列
[Noip2016]蚯蚓 D2 T2 Description 本题中,我们将用符号[c]表示对c向下取整,例如:[3.0」= [3.1」=[3.9」=3.蛐蛐国最近蚯蚓成灾了!隔壁跳 蚤国的跳蚤也拿蚯 ...
- [NOIP2016]愤怒的小鸟 D2 T3 状压DP
[NOIP2016]愤怒的小鸟 D2 T3 Description Kiana最近沉迷于一款神奇的游戏无法自拔. 简单来说,这款游戏是在一个平面上进行的. 有一架弹弓位于(0,0)处,每次Kiana可 ...
- NOIP2016普及总结
---恢复内容开始--- 当时我说如果不出意外有385,结果就这么跪在了第二题,惨啊 本来以为发挥算正常,结果这发挥太不正常了 [T1] 水题啊[趴 注意下细节就好考你会不会写代码. [T2] 这题大 ...
- Noip2016
<这篇是以前的,不开新的了,借版面来换了个标题> 高二了 开学一周,每天被文化课作业碾压... 但是仍然阻挡不了想刷题的心情... 对付noip2016的几块:(有点少,以后补) 高精度( ...
- [NOIP2016]换教室 D1 T3 Floyed+期望DP
[NOIP2016]换教室 D1 T3 Description 对于刚上大学的牛牛来说, 他面临的第一个问题是如何根据实际情况中情合适的课程. 在可以选择的课程中,有2n节课程安排在n个时间段上.在第 ...
- 游记——noip2016
2016.11.18 (day 0) 呆在家. 悠闲地呆在家.. 明后天可能出现的错误: 1)没打freopen.打了ctime: 2)对拍程序忘记怎么写了...忘记随机化种子怎么写了: 3)不知道厕 ...
- NOIP2016报零记
其实,NOIP2016已经于10天之前就结束了,但是由于种种原因,没有写总结. 现在就来填上这个坑吧. DAY1: T1:一道简(kun)单(nan)的模拟,虽然ac,但是考试的时候总觉得怪怪的.并且 ...
- NOIP2016日记
今天下午2:30~4:30考NOIP2016..我4:00前久出来了,没仔细检查.. 错了两道基础题..(T_T) >_< 至少能过..就这样吧..努力复赛!!
随机推荐
- 【kmp+求所有公共前后缀长度】poj 2752 Seek the Name, Seek the Fame
http://poj.org/problem?id=2752 [题意] 给定一个字符串,求这个字符串的所有公共前后缀的长度,按从小到达输出 [思路] 利用kmp的next数组,最后加上这个字符串本身 ...
- 【bzoj1483】[HNOI2009]梦幻布丁 set
[bzoj1483][HNOI2009]梦幻布丁 Description N个布丁摆成一行,进行M次操作.每次将某个颜色的布丁全部变成另一种颜色的,然后再询问当前一共有多少段颜色.例如颜色分别为1,2 ...
- Spoj-FACVSPOW Factorial vs Power
Consider two integer sequences f(n) = n! and g(n) = an, where n is a positive integer. For any integ ...
- substring用法
字符串截取,substring(int beginIndex) 返回一个新的字符串,它是此字符串的一个子字符串. substring(int beginIndex, int endIndex) 返回一 ...
- codeforces 1051 F
多源点最短路. 但是有限制,m - n <= 20,边数 - 点数 <= 20, 所以这个图非常的稀疏. 任意提取出一个生成树出来,LCA处理任意两点最短路. 然后再去遍历那些多余出来的点 ...
- (47)C#运行时序列化
序列化是将对象或对象图转化成字节流的过程.反序列化是将字节流转换回对象图的过程.
- T1230 元素查找 codevs
http://codevs.cn/problem/1230/ 题目描述 Description 给出n个正整数,然后有m个询问,每个询问一个整数,询问该整数是否在n个正整数中出现过. 输入描述 In ...
- 多个Nginx如何实现集群(没具体方案,只是初步探究)
场景: Nginx+Web服务器可以实现负载均衡,但是一台Nginx也是有限的,如果并非量高的话,在他的上层如何实现负载均衡. 如果是DNS或者CDN的话,建多个机房,势必有多个机房数据同步的问题. ...
- winform客户端程序实时读写app.config文件
新接到需求,wcf客户端程序运行时,能实时修改程序的打印机名称: 使用XmlHelper读写 winform.exe.config文件修改后始终,不能实时读取出来,查询博客园,原来已有大神解释了: 获 ...
- JAVA获取前一个月的第一天和最后一天
package com.date; import java.text.SimpleDateFormat; import java.util.Calendar; /** * 默认显示前一个月的第一天和最 ...