20191030
前言
- 第一次交文件……
- 先叙述一下我的没脸的行为:
- T1我的freopen写错了。网站成绩一出后我发现我FE了。
- 然后非常震惊的我飞快的改了freopen交到网站上去,AC了。
- 我痛心疾首心想就当是一次教训吧。
- 结果吃完饭回来公布考试成绩:我AC了!!
- 好像是收卷收晚了我当时已经改了然后收上去是对的?heiheihei。
- T2我还看错题了我修改的是原序列但是我也AC了(kx&skyh也看错了WA70)!!heiheihei。
- 总之这是非常没脸的骗到了130分。
T1
- 其实出题人太善良了,我认为这个题的N和T应该开到1e7的。
- 我的方法是用$\Theta(NlogN)$的时间复杂度内预处理出所有答案然后$\Theta(T)$回答所有询问。
- 设a[i]为满足$x^i>i!$的最小x,显然a[i]随i的增大单调不降。
- 利用double存下倍数并用快速幂实现快速转移就行了。
- 时间复杂度$\Theta(NlogN)$,空间复杂度$\Theta(N)$。
#include<cstdio> int const lt=1e5; double const o=1.0,eps=1e-9; int n; int a[lt|1]; double la; inline double power(double x,int y){ double as=1; for(;y;y>>=1,x=x*x) if(y&1)as=as*x; return as; } int main(){ freopen("yuuutsu.in","r",stdin); freopen("yuuutsu.out","w",stdout); a[1]=2; la=2; for(register int i=2;i<=lt;++i){ a[i]=a[i-1]; la*=(double)a[i]/(double)i; while(la-o<eps) ++a[i],la*=power((double)a[i]/(double)(a[i]-1),i); } int T,x,y; scanf("%d",&T); while(T--){ scanf("%d%d",&x,&y); puts(x<a[y]?"Yes":"No"); } return 0; }
T2
- 直接利用差分。改变序列中的一个位置差分数组中只会有两个位置发生改变。
- 我们把%k相同的位置分为一组,那么每次修改后答案的变化只会取决于对应一组中的最后一个元素。
- 然后就可以直接维护了。
- 考试一眼秒切了,还给kx说这是傻逼题。
- 结果在kx通过大样例1个小时后我才终于调过……
- 时空复杂度$\Theta(N)$。
#include<cstdio> #define ll long long using namespace std; inline int read(){ int ss(0),pp(0);char bb(getchar()); for(;bb<48||bb>57;bb=getchar())pp=bb=='-'; while(bb>=48&&bb<=57)ss=(ss<<1)+(ss<<3)+(bb^48),bb=getchar(); return pp?-ss:ss; } int const N=3e6+5; int n,q,k,lit; int a[N],b[N],c[N]; int la,ct,ps[N]; int main(){ freopen("august.in","r",stdin); freopen("august.out","w",stdout); n=read(),k=read(),q=read(); lit=n-k+1; for(register int i=1;i<=n;++i)a[i]=read(),b[i]=a[i]-a[i-1]; for(register int i=1;i<=lit;++i)c[i+k]=c[i]-b[i]; for(register int i=lit+1;i<=n;++i) if(c[i]!=b[i])++ct; if(ct)puts("No"); else la=1,puts("Yes"); for(register int i=lit;i<=n;++i)ps[i%k]=i; for(register int i=1;i<=q;++i){ int hh=read(),y=read(); int x=ps[hh%k],z=c[x]==b[x]; if(hh<=lit)c[x]-=y; b[hh]+=y; if(z && y)++ct,la=0; else if(!z && c[x]==b[x])la=!--ct; if(++x<=n){ z=c[x]==b[x]; if(hh+1<=lit)c[x]+=y; b[hh+1]-=y; if(z && y)++ct,la=0; else if(!z && c[x]==b[x])la=!--ct; } puts(la?"Yes":"No"); } return 0; }
T3
- dsu on tree。维护方法类似permu,不再赘述。
- 时间复杂度$\Theta(NlogN)$,空间复杂度$\Theta(N)$。
#include<cstdio> #define ll long long inline int read(){ int ss(0);char bb(getchar()); while(bb<48||bb>57)bb=getchar(); while(bb>=48&&bb<=57)ss=(ss<<1)+(ss<<3)+(bb^48),bb=getchar(); return ss; } int const N=2e5+5; int n; int w[N],ps[N]; int head[N],Next[N],to[N],t; int siz[N],son[N]; int l[N],r[N]; ll a[N],ans,tans; inline void add(int x,int y){ to[++t]=y; Next[t]=head[x],head[x]=t; return ; } int dfs(int x){ for(int i=head[x],y,nw=0;i;i=Next[i]){ siz[x]+=dfs(y=to[i]); if(siz[y]>nw)nw=siz[son[x]=y]; } return ++siz[x]; } inline void update(int x,ll y){ tans+=y*(r[x]-l[x]+1)*(r[x]-l[x]+2)>>1; return ; } inline void Get(int x){ l[x]=r[x]=x; int lx=x-1,rx=x+1; if(!l[lx]&&!r[rx]){++tans;return ;} if(l[lx]&&!r[rx])return update(lx,-1),update(r[l[x]=l[lx]]=x,1); if(!l[lx])return update(rx,-1),update(l[r[x]=r[rx]]=x,1); update(lx,-1),update(rx,-1); return update(l[r[l[lx]]=r[rx]]=l[lx],1); } void modify(int x){ Get(ps[x]); for(int i=head[x];i;i=Next[i])modify(to[i]); return ; } void clear(int x){ l[ps[x]]=r[ps[x]]=0; for(int i=head[x];i;i=Next[i])clear(to[i]); return ; } void dsu(int x){ for(int i=head[x];i;i=Next[i]) if(to[i]!=son[x])dsu(to[i]),clear(to[i]),tans=0; if(!son[x]){Get(ps[x]),ans+=(a[x]=tans)*w[x];return ;} dsu(son[x]),Get(ps[x]); ll z=0; for(int i=head[x];i;i=Next[i]) if(to[i]!=son[x])modify(to[i]),z+=a[to[i]]; a[x]=tans,ans+=(tans-z-a[son[x]])*w[x]; return ; } int main(){ freopen("sagittarius.in","r",stdin); freopen("sagittarius.out","w",stdout); n=read(); for(register int i=2;i<=n;++i)add(read(),i); for(register int i=1;i<=n;++i)ps[read()]=i; for(register int i=1;i<=n;++i)w[i]=read(); dfs(1),dsu(1); printf("%lld",ans); return 0; }
rp++