题面:https://www.cnblogs.com/Juve/articles/11712702.html
树:
我太sb了不知道DROT是1,还在sb找根
记录一个fa[]数组,表示x的祖先中第一个智商比x大的,用栈维护
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define re register 6 using namespace std; 7 const int MAXN=1e5+5; 8 int n,q,w[MAXN],sta[MAXN],top=0,rb[MAXN],topp=0,fa[MAXN],deep[MAXN]; 9 int to[MAXN<<1],nxt[MAXN<<1],pre[MAXN],cnt=0; 10 inline void add(re int u,re int v){ 11 ++cnt,to[cnt]=v,nxt[cnt]=pre[u],pre[u]=cnt; 12 } 13 void dfs(int x,int f){ 14 deep[x]=deep[f]+1; 15 int res=0; 16 while(w[x]>w[sta[top]]){ 17 rb[++topp]=sta[top]; 18 --top,++res; 19 } 20 fa[x]=sta[top]; 21 sta[++top]=x; 22 for(int i=pre[x];i;i=nxt[i]){ 23 int y=to[i]; 24 if(y==f) continue; 25 dfs(y,x); 26 } 27 --top; 28 while(res){ 29 sta[++top]=rb[topp--]; 30 --res; 31 } 32 } 33 signed main(){ 34 scanf("%d%d",&n,&q); 35 for(re int i=1;i<=n;++i) scanf("%d",&w[i]); 36 for(re int i=1,u,v;i<n;++i){ 37 scanf("%d%d",&u,&v); 38 add(u,v),add(v,u); 39 } 40 w[0]=0x7fffffff;sta[++top]=0; 41 dfs(1,0); 42 for(re int i=1,u,v,c,res;i<=q;++i){ 43 scanf("%d%d%d",&u,&v,&c); 44 res=0; 45 if(c<w[u]) c=w[u],++res; 46 while(deep[u]>=deep[v]){ 47 if(c<w[u]) c=w[u],++res; 48 u=fa[u]; 49 } 50 if(c<w[v]) ++res; 51 printf("%d\n",res); 52 } 53 return 0; 54 }
环:
没脸抄的方程
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define int long long 6 using namespace std; 7 const int MAXN=1e5+5,mod=1e9+7; 8 int n,e,p[MAXN],q[MAXN],ans; 9 int q_pow(int a,int b,int p){ 10 int res=1; 11 while(b){ 12 if(b&1) res=res*a%p; 13 a=a*a%p; 14 b>>=1; 15 } 16 return res; 17 } 18 signed main(){ 19 scanf("%lld%lld",&n,&e); 20 for(int i=1;i<=n;++i) q[i]=n-1; 21 for(int i=1,u,v;i<=e;++i){ 22 scanf("%lld%lld",&u,&v); 23 ++p[u],--q[u],--q[v]; 24 } 25 ans=n*(n-1)%mod*(n-2)%mod*q_pow(6,mod-2,mod)%mod; 26 for(int i=1;i<=n;++i){ 27 int res=p[i]*(p[i]-1)%mod*q_pow(2,mod-2,mod)%mod+p[i]*q[i]%mod*q_pow(2,mod-2,mod)%mod+q[i]*(q[i]-1)%mod*q_pow(8,mod-2,mod)%mod; 28 ans=(ans-res+mod)%mod; 29 } 30 printf("%lld\n",ans); 31 return 0; 32 }
礼物:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define int long long 6 #define re register 7 using namespace std; 8 const int mod=1e9+7,MAXN=1e7+5,MAXM=1e7+5; 9 int n,a[MAXN],b[MAXN],ans; 10 inline int q_pow(re int a,re int b,re int p){ 11 int res=1; 12 while(b){ 13 if(b&1) res=res*a%p; 14 a=a*a%p; 15 b>>=1; 16 } 17 return res; 18 } 19 int fac[MAXM<<1],inv[MAXM<<1]; 20 inline void get_c(re int N){ 21 fac[0]=fac[1]=inv[0]=1; 22 for(int i=2;i<=N;++i) fac[i]=fac[i-1]*i%mod; 23 inv[N]=q_pow(fac[N],mod-2,mod); 24 for(int i=N-1;i>=1;--i) inv[i]=inv[i+1]*(i+1)%mod; 25 } 26 inline int C(re int n,re int m){ 27 if(m>n) return 0; 28 if(n==m) return 1; 29 return fac[n]*inv[m]%mod*inv[n-m]%mod; 30 } 31 int maxx=0,tong[MAXM<<2],bas=1e7+3; 32 signed main(){ 33 scanf("%lld",&n); 34 for(re int i=1;i<=n;++i){ 35 scanf("%lld%lld",&a[i],&b[i]); 36 maxx=max(maxx,a[i]+b[i]); 37 } 38 get_c(maxx*2+1); 39 for(int i=1;i<=n;++i){ 40 for(int t=-a[i];t<=b[i];++t) ans=(ans+tong[t+bas]*C(a[i]+b[i],a[i]+t)%mod)%mod; 41 for(int t=-b[i];t<=a[i];++t) tong[t+bas]=(tong[t+bas]+C(a[i]+b[i],a[i]-t))%mod; 42 } 43 printf("%lld\n",2*ans%mod); 44 return 0; 45 }
最长不下降子序列:
n有1e12,但值域150,发现它是循环的,处理循环节即可
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define int long long 6 using namespace std; 7 const int MAXN=1e6+5; 8 int n,t,a,b,c,d,p[MAXN],ans=0,maxx=0,cc[MAXN]; 9 int lowbit(int x){ 10 return x&(-x); 11 } 12 void update(int pos,int val){ 13 for(int i=pos;i<=maxx;i+=lowbit(i)){ 14 cc[i]=max(cc[i],val); 15 } 16 } 17 int query(int pos){ 18 int res=0; 19 for(int i=pos;i>0;i-=lowbit(i)){ 20 res=max(res,cc[i]); 21 } 22 return res; 23 } 24 int vis[MAXN]; 25 signed main(){ 26 scanf("%lld%lld%lld%lld%lld%lld",&n,&t,&a,&b,&c,&d); 27 if(n<=1000000){ 28 p[1]=maxx=t; 29 for(int i=2;i<=n;++i){ 30 p[i]=(p[i-1]*p[i-1]%d*a%d+b*p[i-1]%d+c%d)%d; 31 maxx=max(p[i],maxx); 32 } 33 ++maxx; 34 for(int i=1;i<=n;++i){ 35 int res=query(p[i]+1)+1; 36 update(p[i]+1,res); 37 ans=max(ans,res); 38 } 39 printf("%lld\n",ans); 40 return 0; 41 } 42 p[1]=maxx=t; 43 vis[t]=1; 44 int pos=0,q=0;//q:xunhuanchangdu 45 for(int i=2;i<=n;++i){ 46 p[i]=(p[i-1]*p[i-1]%d*a%d+b*p[i-1]%d+c%d)%d; 47 maxx=max(p[i],maxx); 48 if(vis[p[i]]){ 49 pos=i; 50 q=i-vis[p[i]]; 51 break; 52 } 53 vis[p[i]]=i; 54 } 55 ++maxx; 56 if(!pos){ 57 //cout<<pos<<endl; 58 for(int i=1;i<=n;++i){ 59 int res=query(p[i]+1)+1; 60 update(p[i]+1,res); 61 ans=max(ans,res); 62 } 63 printf("%lld\n",ans); 64 return 0; 65 }else{ 66 int len=n-vis[p[pos]]+1; 67 int xh=len/q;//xunhuanjici 68 int ys=len%q;//yuji 69 for(int i=1;i<=pos-1;++i){ 70 int res=query(p[i]+1)+1; 71 update(p[i]+1,res); 72 ans=max(ans,res); 73 } 74 for(int k=1;k<=q;++k){ 75 for(int i=pos;i<=min(n,pos+q-1);++i){ 76 p[i]=p[i-q]; 77 int res=query(p[i]+1)+1; 78 update(p[i]+1,res); 79 int tmp=i-pos+1; 80 res=res+xh-k-1+(tmp<=ys); 81 ans=max(ans,res); 82 } 83 pos=pos+q; 84 } 85 printf("%lld\n",ans); 86 return 0; 87 } 88 return 0; 89 }
完全背包问题:
同余系最短路,咕咕
最近公共祖先:
想到了正解,但不会维护subtree(fa[x])-subtree(x)的信息
考虑dfs序,更新时减去子树x即可
重复染的点可以直接break
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define int long long 6 using namespace std; 7 const int MAXN=1e5+5; 8 int n,m,w[MAXN]; 9 bool vis[MAXN]; 10 int to[MAXN<<1],nxt[MAXN<<1],pre[MAXN],cnt=0; 11 void add(int u,int v){ 12 ++cnt,to[cnt]=v,nxt[cnt]=pre[u],pre[u]=cnt; 13 } 14 int in[MAXN],out[MAXN],fa[MAXN],dfn=0; 15 void dfs(int x){ 16 in[x]=++dfn; 17 for(int i=pre[x];i;i=nxt[i]){ 18 int y=to[i]; 19 if(y==fa[x]) continue; 20 fa[y]=x; 21 dfs(y); 22 } 23 out[x]=dfn; 24 } 25 int tr[MAXN<<2],laz[MAXN<<2]; 26 void down(int k){ 27 tr[k<<1]=max(tr[k<<1],laz[k]); 28 tr[k<<1|1]=max(tr[k<<1|1],laz[k]); 29 laz[k<<1]=max(laz[k<<1],laz[k]); 30 laz[k<<1|1]=max(laz[k<<1|1],laz[k]); 31 laz[k]=0; 32 } 33 void update(int k,int l,int r,int opl,int opr,int val){ 34 if(opl<=l&&r<=opr){ 35 tr[k]=max(tr[k],val); 36 laz[k]=max(laz[k],val); 37 return ; 38 } 39 if(laz[k]) down(k); 40 int mid=(l+r)>>1; 41 if(opl<=mid) update(k<<1,l,mid,opl,opr,val); 42 if(opr>mid) update(k<<1|1,mid+1,r,opl,opr,val); 43 tr[k]=max(tr[k<<1],tr[k<<1|1]); 44 } 45 int query(int k,int l,int r,int opt){ 46 if(l==r) return tr[k]; 47 if(laz[k]) down(k); 48 int mid=(l+r)>>1; 49 if(opt<=mid) return query(k<<1,l,mid,opt); 50 else return query(k<<1|1,mid+1,r,opt); 51 } 52 signed main(){ 53 scanf("%lld%lld",&n,&m); 54 for(int i=1;i<=n;++i){ 55 scanf("%lld",&w[i]); 56 } 57 for(int i=1,u,v;i<n;++i){ 58 scanf("%lld%lld",&u,&v); 59 add(u,v),add(v,u); 60 } 61 dfs(1),vis[0]=1; 62 for(int i=1;i<=m;++i){ 63 char opt[10]; 64 int v,ans; 65 scanf("%s%lld",opt,&v); 66 if(opt[0]==‘M‘){ 67 update(1,1,n,in[v],out[v],w[v]); 68 vis[v]=1; 69 while(vis[fa[v]]!=1){ 70 update(1,1,n,in[fa[v]],in[v]-1,w[fa[v]]); 71 update(1,1,n,out[v]+1,out[fa[v]],w[fa[v]]); 72 v=fa[v]; 73 } 74 }else{ 75 ans=query(1,1,n,in[v]); 76 if(!ans) ans=-1; 77 printf("%lld\n",ans); 78 } 79 } 80 return 0; 81 }
原文:https://www.cnblogs.com/Juve/p/11713753.html