高精硬上彷佛跑不過,其實能夠都取個$log$。那麼只須要比較$y\times log ^x$和$\sum \limits _{i=1}^y log^i$就行了。ios
#include<bits/stdc++.h> using namespace std; int T; double x,y; void work() { scanf("%lf%lf",&x,&y); double res1=y*log2(x); double res2=0; for(int i=1;i<=y;i++) res2+=log2(double(i)); if(res1<=res2)puts("Yes"); else puts("No"); } int main() { freopen("yuuutsu.in","r",stdin); freopen("yuuutsu.out","w",stdout); scanf("%d",&T); while(T--)work(); return 0; }
顯然目標區間合法的充要條件是:把位置按照$mod \ K$意義分組,每組的權值和應該相等。c++
必要性:每次操做對於每一組的改變量都相同,因此最終的和也必然相等。git
充分性:……很顯然吧。spa
直接Hash表維護就行了,每次修改完判斷是否是隻有一種權值和便可。blog
#include<cstdio> #include<iostream> #include<cstring> #define ol using namespace std; int read() { int x=0,f=1;char ch=getchar(); while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch))x=x*10+ch-'0',ch=getchar(); return x*f; } const int N=2e6+5; int n,K,Q,a[N],sum[N]; struct Hashtable { #define mod 19260817 int tot,head[19260820],nxt[N],to[N],val[N]; int &operator [] (int v) { int x=v%mod; for(int i=head[x];i;i=nxt[i]) if(to[i]==v)return val[i]; to[++tot]=v;nxt[tot]=head[x]; head[x]=tot; return val[tot]=0; } }s; int main() { #ifdef ol freopen("august.in","r",stdin); freopen("august.out","w",stdout); #endif n=read();K=read();Q=read(); for(int i=1;i<=n;i++) a[i]=read(); for(int i=1;i<=n;i++) sum[i%K]+=a[i]; for(int i=0;i<K;i++) s[sum[i]]++; if(s[sum[0]]==K)puts("Yes"); else puts("No"); while(Q--) { int x=read(),val=read(); a[x]+=val; s[sum[x%K]]--; sum[x%K]+=val; s[sum[x%K]]++; if(s[sum[0]]==K)puts("Yes"); else puts("No"); } return 0; }
構造一個新的點權$v'[x]=v[x]-v[fa[x]]$,那麼區間權值就成了區間內全部元素的$lca$的權值和,從每一個點的角度考慮就是它做爲一些連續點的祖先的方案數再乘上點權。get
對於每一個點建一棵線段樹,維護左側起最長連續段的端點,右側起最長連續段的端點和方案數,線段樹合併便可,維護過程相似於《山海經》。string
方案數就是能夠取的連續區間數,即$\frac {(r-l+1)(r-l+2)}{2}$,除以2能夠留在外面作。it
#include<cstdio> #include<iostream> #include<cstring> #define ol using namespace std; typedef long long ll; int read() { int x=0,f=1;char ch=getchar(); while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch))x=x*10+ch-'0',ch=getchar(); return x*f; } const int N=2e5+5; int n,fa[N],a[N],pos[N]; int to[N<<1],head[N],nxt[N<<1],tot; ll v[N],ans; void add(int x,int y) { to[++tot]=y; nxt[tot]=head[x]; head[x]=tot; } int root[N],type,lp[N*30],rp[N*30],ls[N*30],rs[N*30]; ll w[N*30]; void up(int k,int l,int r) { int mid=l+r>>1; lp[k]=lp[ls[k]];rp[k]=rp[rs[k]]; w[k]=w[ls[k]]+w[rs[k]]; if(rp[ls[k]]&&lp[rs[k]]) { w[k]-=1LL*(mid-rp[ls[k]]+1)*(mid-rp[ls[k]]+2)+1LL*(lp[rs[k]]-mid)*(lp[rs[k]]-mid+1); w[k]+=1LL*(lp[rs[k]]-rp[ls[k]]+1)*(lp[rs[k]]-rp[ls[k]]+2); } if(lp[ls[k]]==mid)lp[k]=lp[rs[k]]?lp[rs[k]]:mid; if(rp[rs[k]]==mid+1)rp[k]=rp[ls[k]]?rp[ls[k]]:mid+1; } void update(int &k,int l,int r,int pos) { if(!k)k=++type; if(l==r) { lp[k]=rp[k]=l;w[k]=2; return ; } int mid=l+r>>1; if(pos<=mid)update(ls[k],l,mid,pos); else update(rs[k],mid+1,r,pos); up(k,l,r); } int merge(int x,int y,int l,int r) { if(!x||!y)return x+y; if(l==r)return x; int mid=l+r>>1; ls[x]=merge(ls[x],ls[y],l,mid); rs[x]=merge(rs[x],rs[y],mid+1,r); up(x,l,r); return x; } void dfs(int x) { update(root[x],1,n,pos[x]); for(int i=head[x];i;i=nxt[i]) { int y=to[i]; dfs(y); merge(root[x],root[y],1,n); } ans+=w[root[x]]/2*v[x]; } int main() { #ifdef ol freopen("sagittarius.in","r",stdin); freopen("sagittarius.out","w",stdout); #endif n=read(); for(int i=2;i<=n;i++) { fa[i]=read(); add(fa[i],i); } for(int i=1;i<=n;i++) a[i]=read(),pos[a[i]]=i; for(int i=1;i<=n;i++) v[i]=read(); for(int i=n;i;i--) v[i]-=v[fa[i]]; dfs(1); printf("%lld\n",ans); return 0; }