[2017/5/28]FJ四校联考
来自FallDream的博客,未经允许,请勿转载,谢谢。
话说这一段时间算是过去了,好久好久之后终于又有联考了 没想到这次到我们学校出题,昨天才想起来,临时花一天赶了一套,我出了一个sbFFT,质量勉强吧。
upd:代码已经更新
A.种树
有一棵二叉树,有点权,你要从节点1出发前往一个节点,如果路上的节点权值和他相等就结束,否则比他小向左,比他大向右,问能不能找到。
需要支持多组询问,单点修改,子树反转
n,m<=10^5
#include<iostream>
#include<cstdio>
#define pa pair<int,int>
#define mp(x,y) make_pair(x,y)
#define MN 100000
#define INF 2000000000
using namespace std;
inline int read()
{
int x = , f = ; char ch = getchar();
while(ch < '' || ch > ''){ if(ch == '-') f = -; ch = getchar();}
while(ch >= '' && ch <= ''){x = x * + ch - '';ch = getchar();}
return x * f;
} struct data{int lmn,lmx,rmn,rmx;
friend data operator +(data a,data b)
{
data c;
c.lmn=min(a.lmn,b.lmn);
c.rmx=max(a.rmx,b.rmx);
c.lmx=(a.lmx==INF)?b.lmx:(b.lmx==INF?a.lmx:max(a.lmx,b.lmx));
c.rmn=(a.rmn==-INF)?b.rmn:(b.rmn==-INF?a.rmn:min(a.rmn,b.rmn));
return c;
}
void rev()
{
swap(lmn,rmn);if(lmn==-INF) lmn=INF;if(rmn==INF) rmn=-INF;
swap(lmx,rmx);if(rmx==INF) rmx=-INF;if(lmx==-INF)lmx=INF;
}
};
struct Tree{int l,r,rev;data x;}T[MN*+];
int l[MN+],r[MN+],num[MN+],fa[MN+],top[MN+],n,m,w[MN+],dn=,nl[MN+],nr[MN+],size[MN+];
pa p[MN+]; void Dfs1(int x)
{
if(l[x]) Dfs1(l[x]),fa[l[x]]=x;
if(r[x]) Dfs1(r[x]),fa[r[x]]=x;
size[x]=size[l[x]]+size[r[x]]+;
} void Dfs2(int x,int tp)
{
if(!x) return;top[x]=tp;num[nl[x]=++dn]=x;
if(size[l[x]]>size[r[x]]) Dfs2(l[x],tp),Dfs2(r[x],r[x]);
else Dfs2(r[x],tp),Dfs2(l[x],l[x]);
p[l[x]]=mp(,w[x]);p[r[x]]=mp(,w[x]);
nr[x]=dn;
} void build(int x,int l,int r)
{
if((T[x].l=l)==(T[x].r=r))
{
int now=num[l];
if(p[now].first==)
T[x].x=(data){p[now].second,p[now].second,-INF,-INF};
else
T[x].x=(data){INF,INF,p[now].second,p[now].second};
return;
}
int mid=l+r>>;
build(x<<,l,mid);build(x<<|,mid+,r);
T[x].x=T[x<<].x+T[x<<|].x;
} inline void Mark(int x)
{
T[x].rev^=;
T[x].x.rev();
} inline void pushdown(int x)
{
Mark(x<<);Mark(x<<|);
T[x].rev=;
} void Modify(int x,int v,pa k)
{
if(T[x].l==T[x].r)
{
if(k.first==^T[x].rev)
T[x].x=(data){k.second,k.second,-INF,-INF};
else
T[x].x=(data){INF,INF,k.second,k.second};
return;
}
if(T[x].rev) pushdown(x);
int mid=(T[x].l+T[x].r)>>;
if(v<=mid) Modify(x<<,v,k);
else if(v>mid) Modify(x<<|,v,k);
T[x].x=T[x<<].x+T[x<<|].x;
} void Reverse(int x,int l,int r)
{
if(T[x].l==l&&T[x].r==r){Mark(x);return;}
int mid=(T[x].l+T[x].r)>>;
if(T[x].rev) pushdown(x);
if(r<=mid) Reverse(x<<,l,r);
else if(l>mid) Reverse(x<<|,l,r);
else Reverse(x<<,l,mid),Reverse(x<<|,mid+,r);
T[x].x=T[x<<].x+T[x<<|].x;
} data Query(int x,int l,int r)
{
if(T[x].l==l&&T[x].r==r) return T[x].x;
if(T[x].rev) pushdown(x);
int mid=(T[x].l+T[x].r)>>;
if(r<=mid) return Query(x<<,l,r);
else if(l>mid) return Query(x<<|,l,r);
else return Query(x<<,l,mid)+Query(x<<|,mid+,r);
} data Solve(int x)
{
data res=(data){INF,INF,-INF,-INF};
for(;x;x=fa[top[x]]) res=res+Query(,nl[top[x]],nl[x]);
return res;
} int main()
{
n=read();m=read();
for(int i=;i<=n;++i) w[i]=read(),l[i]=read(),r[i]=read();
Dfs1();Dfs2(,);p[]=mp(,INF);build(,,n);
for(int i=;i<=m;++i)
{
int op=read(),x=read();
if(op==)
{
int y=read();
if(l[x]) Modify(,nl[l[x]],mp(,y));
if(r[x]) Modify(,nl[r[x]],mp(,y));
w[x]=y;
}
if(op==)
{
if(nl[x]!=nr[x])
Reverse(,nl[x]+,nr[x]);
}
if(op==)
{
data y=Solve(x);
if(w[x]<y.lmn&&w[x]>y.rmx) puts("YES");
else puts("NO");
}
}
return ;
}
把一条边看成一个限制条件,也就是大于或者小于某个值。那么树链剖分之后线段树维护就行了,维护区间小于限制的最大/最小值,大于限制的最大/最小值。
子树反转可以打标记实现。复杂度nlog^2n
代码貌似丢在学校了,端午过后补吧。
B.mark
C.秋之国的盛会
给定两个长度为n的序列ai,bi,可以把a向后推动0到n次。给定c,m,推动k次的时候的费用是$\sum{(\frac{ai}{bi}-c*k-m)^2}$
n<=10^5
求最小费用
把这个式子展开,很容易发现只要能快速求出不同推动状态下的$\sum{\frac{ai}{bi}}$和$\sum{(\frac{ai}{bi})^2}$即可。
把ai数组倒过来并复制一遍,b数组变成1/bi,fft求卷积即可。另一项同理。
复杂度nlogn
#include<iostream>
#include<cstdio>
#include<cmath>
#define pi acos(-1)
#define ld long double
#define MN 262144
using namespace std;
inline int read()
{
int x = , f = ; char ch = getchar();
while(ch < '' || ch > ''){ if(ch == '-') f = -; ch = getchar();}
while(ch >= '' && ch <= ''){x = x * + ch - '';ch = getchar();}
return x * f;
} int N,n,M;double cost;
struct cp
{
ld r,u;
cp ( double x = ,double y = ) :r(x) , u(y) {}
cp operator + (const cp&y) { return cp(r+y.r,u+y.u);}
cp operator - (const cp&y) { return cp(r-y.r,u-y.u);}
cp operator * (const cp&y) { return cp(r*y.r-u*y.u,r*y.u+u*y.r);}
cp operator * (ld y){return cp(r*y,u*y);}
cp operator / (ld y){return cp(r/y,u/y);}
}A[MN+],B[MN+],C[MN+],a[MN+],b[MN+],c[MN+],w[][MN+]; void fft(cp*x,int r)
{
for(int i=,j=;i<N;++i)
{
if(i>j) swap(x[i],x[j]);
for(int l=N>>;(j^=l)<l;l>>=);
}
for(int i=;i<=N;i<<=)for(int j=;j<N;j+=i)for(int k=;k<i>>;++k)
{
cp t=x[j+k+(i>>)]*w[r][N/i*k];
x[j+k+(i>>)]=x[j+k]-t;
x[j+k]=x[j+k]+t;
}
if(r)for(int i=;i<N;++i) x[i]=x[i]/N;
} int main()
{
freopen("party.in","r",stdin);
freopen("party.out","w",stdout);
n=read();M=read();scanf("%lf",&cost);
for(int i=n-;~i;--i) a[i].r=read(),A[i].r=a[i].r*a[i].r;
for(int i=;i<n;++i) b[i].r=(ld)/read(),B[i].r=b[i].r*b[i].r;
for(int i=;i<n;++i) a[i+n]=a[i],A[i+n]=A[i];
for(N=;N<=n<<;N<<=);
w[][]=w[][N]=cp(,);w[][]=w[][N-]=cp(cos(*pi/N),sin(*pi/N));
for(int i=;i<=N;++i) w[][i]=w[][N-i]=w[][i-]*w[][];
fft(a,);fft(b,);fft(A,);fft(B,);
for(int i=;i<N;++i) c[i]=a[i]*b[i],C[i]=A[i]*B[i];
fft(c,);fft(C,);
ld ans=1e99;int mx=;
for(int i=n-;i<n<<;++i)
{
ld j=cost*(i-n+);
if(C[i].r-*c[i].r*(j+M)+(ld)n*(j+M)*(j+M)<ans) mx=i-n+;
ans=min(ans,C[i].r-*c[i].r*(j+M)+(ld)n*(j+M)*(j+M));
}
printf("%.10lf",(double)ans);
return ;
}
[2017/5/28]FJ四校联考的更多相关文章
- 【四校联考】【比赛题解】FJ NOIP 四校联考 2017 Round 7
此次比赛为厦门一中出题.都是聚劳,不敢恭维. 莫名爆了个0,究其原因,竟然是快读炸了……很狗,很难受. 话不多说,来看看题: [T1] 题意: 样例: PS:1<=h[i]<=100000 ...
- [四校联考P3] 区间颜色众数 (主席树)
主席树 Description 给定一个长度为 N 颜色序列A,有M个询问:每次询问一个区间里是否有一种颜色的数量超过了区间的一半,并指出是哪种颜色. Input 输入文件第一行有两个整数:N和C 输 ...
- 四校联考 tree3
我们考虑计算红色点与非红色点的对数. 我们用f[i][j]表示i的子树中有j个红色点的概率,将i所有子树合并. 接着我们对于每一个状态,枚举i是红色还是非红色算概率. 同时我们可以求出i和i子树内一个 ...
- [3.19FJ四校联考]
来自FallDream的博客.未经允许,请勿转载,谢谢. ---------------------------------------------------- A.积分,不会 以后补 B.给定一 ...
- szoj461【四校联考0430】挑战
传送门:(涉及版权忽略) [题解] 我们发现n的范围很小,提示我们可以折半,然后我们就会了O(T2^(n/2)*n)的做法,然而会T. 考虑如何优化.直接排序会多一个log(2^(n/2))也就是n, ...
- 三校联考 Day3
三校联考 Day3 大水题 题目描述:给出一个圆及圆上的若干个点,问两个点间的最远距离. solution 按极角排序,按顺序枚举,显然距离最远的点是单调的,线性时间可解出答案. 大包子的束缚 题目描 ...
- 【赛时总结】NOIP2018-三校联考1024
◇NOIP三校联考-1024◇ 发现以前的博客写得似乎都很水……基本上都没什么阅读量QwQ 决定改过自新╰( ̄ω ̄o) 就从这篇博客开始吧~ 现场考得无地自容,看到题解才发现一些东西……(我第三题还没 ...
- [2019多校联考(Round 6 T3)]脱单计划 (费用流)
[2019多校联考(Round 6 T3)]脱单计划 (费用流) 题面 你是一家相亲机构的策划总监,在一次相亲活动中,有 n 个小区的若干男士和 n个小区的若干女士报名了这次活动,你需要将这些参与者两 ...
- [多校联考2019(Round 5 T1)] [ATCoder3912]Xor Tree(状压dp)
[多校联考2019(Round 5)] [ATCoder3912]Xor Tree(状压dp) 题面 给出一棵n个点的树,每条边有边权v,每次操作选中两个点,将这两个点之间的路径上的边权全部异或某个值 ...
随机推荐
- Python IDE Spyder的简单介绍
最近深度学习发展非常迅猛,大有一统江湖的趋势.经过一段时间学习,发现自己对这种神奇的玄学非常感兴趣,希望能够进一步的研究.而这种研究性学科单纯地看论文比较难以明白,所以希望能够跟进大牛们写的代码深入学 ...
- MongoDb进阶实践之三 MongoDB查询命令详述
一.引言 上一篇文章我们已经介绍了MongoDB数据库的最基本操作,包括数据库的创建.使用和删除数据库,文档的操作也涉及到了文档的创建.删除.更新和查询,当然也包括集合的创建.重命 ...
- C++ 实现一个信号量
C++ 实现一个信号量 信号量有很多应用场景,事实上只要是生产者-消费者模型,一般都需要一个信号量来控制. POSIX接口是有PV信号量API的.但C++标准没有.下面是一个PV信号量的简单实现.有些 ...
- 基于dns搭建eureka集群
eureka集群方案: 1.通常我们部署的eureka节点多于两个,根据实际需求,只需要将相邻节点进行相互注册(eureka节点形成环状),就达到了高可用性集群,任何一个eureka节点挂掉不会受到影 ...
- 新概念英语(1-115)Knock! Knock!
Lesson 115 Knock, knock! 敲敲门! Listen to the tape then answer this question. What does Jim have to dr ...
- SpringCloud是否值得引入?
中小型互联网公司微服务实践-经验和教训 http://xujin.org/sc/sc-zq/#more Spring Cloud在国内中小型公司能用起来吗?https://mp.weixin.qq.c ...
- GIT入门笔记(4)- GIT 安装
关于Windows下的安装工具-msysgit Windows下要使用很多Linux/Unix的工具时,需要Cygwin这样的模拟环境,Git也一样. Cygwin的安装和配置都比较复杂,不建议直接折 ...
- Linux实战案例(2)实例讲解使用软连接的场景和过程
=================================== 使用场景:使用软连接简化版本切换动作 进入操作目录, cd /opt/modules/ ==================== ...
- Spring Security 入门(3-10)Spring Security 的四种使用方式
原文链接: http://www.360doc.com/content/14/0724/17/18637323_396779659.shtml 下面是作者的一个问题处理
- 翻译:JVM虚拟机规范1.7中的运行时常量池部分(一)
原文链接: https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.4 Java Virtual Machine i ...