ZJU-Summer Camp Problem
Day 1
NTT
#include <bits/stdc++.h> #define inf 0x3f3f3f3f #define m_k make_pair #define mod 998244353 #define int long long using namespace std; const int N=4*1e5+100; int n,l,c,len,inv[N],rev[N],f[N],g[N]; int fac[N]; inline int m_pow(int a,int b) { a%=mod; int ans=1; while (b) { if (b&1) ans=(ans*a)%mod; b>>=1; a=(a*a)%mod; } return ans; } inline void change(int len) { for (int i=0;i<len;i++) { rev[i]=rev[i>>1]>>1; if (i&1) rev[i]|=len>>1; } } inline int ntt(int y[],int len,int v) { for (int i=0;i<len;i++) if (i<rev[i]) swap(y[i],y[rev[i]]); for (int i=2;i<=len;i<<=1) { int step=m_pow(3,(mod-1)/i); if (v==-1) step=m_pow(step,mod-2); for (int j=0;j<len;j+=i) { int x=1; for (int k=j;k<j+i/2;k++) { int a=y[k],b=(x*y[k+i/2])%mod; y[k]=(a+b)%mod; y[k+i/2]=(a-b+mod)%mod; x=(x*step)%mod; } } } if (v==-1) { int invlen=m_pow(len,mod-2); for (int i=0;i<len;i++) y[i]=(y[i]*invlen)%mod; } } signed main() { scanf("%lld%lld%lld",&n,&l,&c); c%=mod; if (c==1) { for (int i=1;i<=n;i++) printf("%lld\n",l%mod); return 0; } fac[0]=1; for (int i=1;i<=n;i++) fac[i]=(fac[i-1]*i)%mod; inv[n]=m_pow(fac[n],mod-2); for (int i=n-1;i>=0;i--) inv[i]=(inv[i+1]*(i+1))%mod; len=1; while (len<=2*n) len<<=1; int invc=m_pow(c,mod-2); for (int i=0;i<=n;i++) { f[i]=inv[i]; if (i==1) f[i]=(f[i]*l)%mod; else { int tmp; if (i==0) tmp=c; else tmp=m_pow(invc,i-1); f[i]=(f[i]*tmp)%mod; f[i]=(f[i]*(1-m_pow(tmp,l)+mod)%mod)%mod; f[i]=(f[i]*m_pow(1-tmp+mod,mod-2))%mod; } if (i&1) f[i]=(mod-f[i])%mod; } change(len); ntt(f,len,1),ntt(g,len,1); for (int i=0;i<len;i++) f[i]=(f[i]*g[i])%mod; ntt(f,len,-1); int ret=c; ret=(ret*(1-m_pow(c,l)+mod)%mod)%mod; ret=(ret*m_pow(1-c+mod,mod-2))%mod; for (int i=1;i<=n;i++) f[i]=(ret-(f[i]*fac[i])%mod+mod)%mod; int ans=0; for (int i=1;i<=n;i++) printf("%lld\n",f[i]); }
二分套二分
#pragma GCC optimize(2) #include <bits/stdc++.h> #define inf 0x3f3f3f3f #define m_k make_pair #define int long long using namespace std; const int N=2*1e5+100; int n,m,w,b[N],vi[N],h[N],k; int MAX,f[N][21],lg[N]; long long si[N],sum[N],ans; struct node { int l,r,L,R,id; }sh[N]; node a[N],c[N]; inline int min(int a,int b){return((a<b)?a:b);} inline int max(int a,int b){return((a>b)?a:b);} inline int read() { int f=1,x=0;char s=getchar(); while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();} while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();} return x*f; } bool cmp(node a,node b) { return (a.L<b.L || (a.L==b.L && a.R<b.R)); } bool cmp1(node a,node b) { return (a.l<b.l || (a.l==b.l && a.r<b.r)); } namespace tree { int sh[N]; inline int lowbit(int x){return(x&(-x));} inline void change(int x,int v) { while (x>0) { sh[x]+=v; x-=lowbit(x); } } inline int query(int x) { int ans=0; while (x<=w) { ans+=sh[x]; x+=lowbit(x); } return ans; } } inline void uni() { int r=n;n=0; for (int i=1;i<=r;) { c[++n]=sh[i]; int j=i; while (j<=r && sh[i].L==sh[j].L && sh[i].R==sh[j].R) j++; i=j; } for (int i=1;i<=n;i++) sh[i]=c[i]; } inline int get(int l,int r) { int len=r-l+1,p=lg[len]; return max(f[l][p],f[r-(1<<p)+1][p]); } inline int find_l(int i){return lower_bound(h+1,h+1+k,a[i].l)-h;} inline int find_r(int i){return upper_bound(h+1,h+1+k,a[i].r)-h-1;} signed main() { m=read(),n=read(); for (int i=1;i<=n;i++) { sh[i].l=read(),sh[i].r=read(); b[++w]=sh[i].l,b[++w]=sh[i].r; } sort(b+1,b+1+w); w=unique(b+1,b+1+w)-b-1; for (int i=1;i<=n;i++) { sh[i].L=lower_bound(b+1,b+1+w,sh[i].l)-b; sh[i].R=lower_bound(b+1,b+1+w,sh[i].r)-b; sh[i].id=i; } sort(sh+1,sh+1+n,cmp); uni(); for (int i=1;i<=n;) { int j=i; while (j<=n && sh[j].L==sh[i].L) { tree::change(sh[j].R,1); j++; } for (int k=i;k<j;k++) { tree::change(sh[k].R,-1); if (tree::query(sh[k].R)!=0) vi[k]=1; tree::change(sh[k].R,1); } i=j; } w=0; for (int i=1;i<=n;i++) if (!vi[i]) a[++w]=sh[i]; sort(a+1,a+1+w,cmp1); for (int i=1;i<=w;i++) f[i][0]=a[i].r-a[i].l,lg[i]=log(i)/log(2); for (int j=1;j<=20;j++) { for (int i=1;i<=w;i++) { if (i+(1<<j)-1>w) break; f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]); } } while (m--) { ans=0; k=read(); for (int i=1;i<=k;i++) h[i]=read(); sort(h+1,h+1+k); for (int i=1;i<=k;i++) si[i]=si[i-1]+1ll*i*h[i],sum[i]=sum[i-1]+h[i]; for (int i=1;i<=w;) { int l=i,r=w,nowl=find_l(i),nowr=find_r(i); while (l<r) { int mid=l+((r-l+1)>>1); if (find_l(mid)==nowl && find_r(mid)==nowr) l=mid; else r=mid-1; } ans=max(ans,1ll*get(i,l)+si[nowr]-si[nowl-1]-1ll*(nowl-1)*(sum[nowr]-sum[nowl-1])); i=l+1; } printf("%lld\n",ans); } }
广义SAM
wqs二分+随机化扰动
#include <bits/stdc++.h> #define mod 1000000007 #define inv2 500000004 #define int long long using namespace std; const int N=4641588,M=1e5+100; int n,phi[N+100],v[N+100],p[N],w; unordered_map <int,int> get_phi; int getphi(int n) { if (n<=N) return phi[n]; if (get_phi[n]) return get_phi[n]; int ans=((n%mod)*((n+1)%mod))%mod; ans=(ans*inv2)%mod; for (int l=2,r;l<=n;l=r+1) { r=n/(n/l); ans=(ans-getphi(n/l)*((r-l+1)%mod)%mod+mod)%mod; } get_phi[n]=ans; return ans; } inline int f(int n) { return (2*getphi(n)%mod-1+mod)%mod; } signed main() { scanf("%lld",&n); phi[1]=1; for (int i=2;i<=N;i++) { if (!v[i]) { v[i]=i,p[++w]=i; phi[i]=i-1; } for (int j=1;j<=w;j++) { if (p[j]>v[i] || p[j]>N/i) break; v[p[j]*i]=v[i]; if (i%p[j]==0) phi[i*p[j]]=(phi[i]*p[j])%mod; else phi[i*p[j]]=(phi[i]*(p[j]-1))%mod; } } for (int i=1;i<=N;i++) phi[i]=(phi[i]+phi[i-1])%mod; int ans=0; for (int l=1,r;l<=n;l=r+1) { r=n/(n/l); ans=(ans+((getphi(r)-getphi(l-1)+mod)%mod*f(n/l))%mod)%mod; } printf("%lld\n",ans); }
LCT
#include <bits/stdc++.h> using namespace std; const int N=3*1e5+100; int n,m,son[N][2],fa[N],tag[N],root; int sz[N],place[N],now,realson[N],minde[N]; int tot,first[N],nxt[N*2],point[N*2]; struct node { int val,id; }sh[N]; long long ret,ans,val[N],sum[N]; inline void add_edge(int x,int y) { tot++; nxt[tot]=first[x]; first[x]=tot; point[tot]=y; } inline int read() { int f=1,x=0;char s=getchar(); while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();} while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();} x*=f; return x; } inline int sf(int x) { return (son[fa[x]][1]==x); } inline bool nroot(int x) { return (son[fa[x]][0]==x||son[fa[x]][1]==x); } inline void rev(int x) { swap(son[x][0],son[x][1]); tag[x]^=1; } inline void pushup(int x) { sum[x]=sum[son[x][0]]+sum[son[x][1]]+val[x]; if (son[x][0]) minde[x]=minde[son[x][0]]; else minde[x]=x; } inline void pushdown(int x) { if (tag[x]) { if (son[x][0]) rev(son[x][0]); if (son[x][1]) rev(son[x][1]); tag[x]=0; } } inline void pushall(int x) { if (nroot(x)) pushall(fa[x]); pushdown(x); } inline void connect(int x,int y,int dir) { son[y][dir]=x; fa[x]=y; } inline void rotate(int x) { int f,gf,xd,fd,s; f=fa[x],gf=fa[f],xd=sf(x),fd=sf(f),s=son[x][xd^1]; if (nroot(f)) connect(x,gf,fd); connect(f,x,xd^1); if (s) connect(s,f,xd); fa[x]=gf,son[f][xd]=s; pushup(f),pushup(x); } inline void splay(int x) { pushall(x); while (nroot(x)) { if (!nroot(fa[x])) rotate(x); else if (sf(fa[x])==sf(x)) rotate(fa[x]),rotate(x); else rotate(x),rotate(x); } } inline void access(int x) { for (int y=0;x;x=fa[x]) { splay(x); son[x][1]=y; if (y==0) realson[x]=0; else realson[x]=minde[y]; if (place[x]<=now) val[x]=n-sz[x]-sz[minde[y]]; pushup(x); y=x; root=x; } } inline void makeroot(int x) { access(x); splay(x); rev(x); } inline int findroot(int x) { access(x); splay(x); while (son[x][0]) pushdown(x),x=son[x][0]; splay(x); return x; } inline void link(int x,int y) { makeroot(x); if (findroot(y)!=x) fa[x]=y; } void dfs(int x,int fa) { if (x!=1) link(x,fa); sz[x]=1; for (int i=first[x];i!=-1;i=nxt[i]) { int u=point[i]; if (u==fa) continue; dfs(u,x); sz[x]+=sz[u]; } } inline bool cmp(node a,node b) { return a.val>b.val; } int main() { tot=-1; memset(first,-1,sizeof(first)); memset(nxt,-1,sizeof(nxt)); n=read(); for (int i=1;i<=n;i++) sh[i].val=read(),sh[i].id=i,minde[i]=i; sort(sh+1,sh+1+n,cmp); for (int i=1;i<=n;i++) place[sh[i].id]=i; for (int i=1;i<n;i++) { int u,v; u=read(),v=read(); add_edge(u,v); add_edge(v,u); // link(u,v); } dfs(1,1);makeroot(1); for (int i=1;i<=n;) { // if (minde[0]!=0) printf("OK\n"); now=i-1; int j=i; while (j<=n && sh[i].val==sh[j].val) { access(sh[j].id); ans+=ret+sum[root]; j++; } for (int k=i;k<j;k++) { int x=sh[k].id; ret+=sz[x]; if (realson[x]!=0) { splay(x); val[x]=n-sz[x]-sz[realson[x]]; pushup(x); } } i=j; } printf("%lld\n",ans); }
主席树
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> #include<vector> #include<queue> typedef long long ll; typedef unsigned un; typedef std::string str; typedef std::pair<ll,ll> pll; ll read(){ll x=0,f=1;char c=getchar();while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}return f*x;} ll max(ll a,ll b){return a>b?a:b;} void umax(ll& a,ll t){if(t>a)a=t;} const ll INF=1ll<<58; #define MAXN 300011 ll diff,fx[MAXN],a[MAXN],c=0; ll place(ll val){return std::lower_bound(fx+1,fx+diff+1,val)-fx;} struct Edge { ll v,nxt; }e[MAXN<<1|1]; ll ecnt=0,last[MAXN]; void adde(ll u,ll v) { ++ecnt; e[ecnt].v=v; e[ecnt].nxt=last[u],last[u]=ecnt; } ll dfn[MAXN],ed[MAXN],w[MAXN],fa[MAXN], cur=0; void dfs(ll u) { dfn[u]=++cur;w[cur]=a[u]; for(ll i=last[u];i;i=e[i].nxt) { ll v=e[i].v; if(v==fa[u])continue; fa[v]=u; dfs(v); } ed[u]=cur; } struct node { ll sum; int lson,rson; }t[MAXN<<5|1]; int root[MAXN],cnt=0,n; #define rt t[num] void insert(int pre,int& num,un pos,un l=1,un r=diff) { num=++cnt; rt=t[pre],++rt.sum; if(l==r)return; un mid=(l+r)>>1; if(pos<=mid)insert(t[pre].lson,rt.lson,pos,l,mid); else insert(t[pre].rson,rt.rson,pos,mid+1,r); } void Qsum(int pre,int num,un pos,un l=1,un r=diff) { if(!pos)return; if(l==r){c+=rt.sum-t[pre].sum;return;} un mid=(l+r)>>1; if(pos<=mid)Qsum(t[pre].lson,rt.lson,pos,l,mid); else { c+=t[rt.lson].sum-t[t[pre].lson].sum; Qsum(t[pre].rson,rt.rson,pos,mid+1,r); } } int main() { n=read(); for(ll i=1;i<=n;++i)fx[++diff]=a[i]=read(); std::sort(fx+1,fx+diff+1),diff=std::unique(fx+1,fx+diff+1)-fx-1; for(ll i=1;i<n;++i){ll u=read(),v=read();adde(u,v),adde(v,u);} dfs(1); for(ll i=1;i<=n;++i)w[i]=place(w[i]),insert(root[i-1],root[i],w[i]); ll ans=0; for(ll u=1;u<=n;++u) { for(ll i=last[u];i;i=e[i].nxt) { ll v=e[i].v; if(v==fa[u]) { c=0; Qsum(root[0],root[dfn[u]-1],w[dfn[u]]-1),Qsum(root[ed[u]],root[n],w[dfn[u]]-1); ans+=c*(ed[u]-dfn[u]+1); continue; } c=0; Qsum(root[dfn[v]-1],root[ed[v]],w[dfn[u]]-1); //printf("%lld nodes in sub(%lld)\n",c,v); ans+=c*(n-(ed[v]-dfn[v]+1)); } } printf("%lld",ans); return 0; }
树状数组
#include <algorithm> #include <cassert> #include <cmath> #include <cstdio> #include <cstdlib> #include <cstring> #include <ctime> #include <iostream> #include <map> #include <queue> #include <set> #include <vector> #define m_p make_pair #define sz(x) (int)x.size() #define out(x) cerr<<#x<<" = "<<x<<" " #define outln(x) cerr<<#x<<" = "<<x<<endl #define outarr(x,l,r) cerr<<#x"["<<l<<"-"<<r<<"] = "; for (int _i=l;_i<=r;++_i) cerr<<x[_i]<<" ";cerr<<endl; using namespace std; typedef long long ll; typedef pair<int,int> pii; #define gc() getchar() //char buf[1<<23],*p1=buf,*p2=buf; //#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++) template <class T> void read(T &x) { x=0; char c=gc(); int flag=0; while (c<'0'||c>'9') flag|=(c=='-'),c=gc(); while (c>='0'&&c<='9') x=(x<<3)+(x<<1)+(c^48),c=gc(); if (flag) x=-x; } template <class T> T _max(T a,T b){return a>b ? a : b;} template <class T> T _min(T a,T b){return a<b ? a : b;} template <class T> bool checkmax(T &a,T b){return b>a ? a=b,1 : 0;} template <class T> bool checkmin(T &a,T b){return b<a ? a=b,1 : 0;} const int N=300005; int n,a[N],sz[N],dfn[N],dfs_clock=0,p[N],fa[N]; vector <int> G[N]; void add_edge(int x,int y) { G[x].push_back(y); } void dfs(int x,int f) { sz[x]=1; dfn[x]=++dfs_clock; fa[x]=f; for (int i=0;i<sz(G[x]);++i) { int to=G[x][i]; if (to==f) continue; dfs(to,x); sz[x]+=sz[to]; } } void init() { read(n); for (int i=1;i<=n;++i) { read(a[i]); } for (int i=1,u,v;i<n;++i) { read(u); read(v); add_edge(u,v); add_edge(v,u); } dfs(1,0); } bool cmp(int x,int y){return a[x]<a[y];} namespace BIT { int C[N]; void update(int x,int num) { for (;x<=n;x+=(x&(-x))) C[x]+=num; } int query(int x) { int ans=0; for (;x;x-=(x&(-x))) ans+=C[x]; return ans; } int query(int l,int r) { return query(r)-query(l-1); } } void solve() { ll ans=0; for (int i=1;i<=n;++i) p[i]=i; sort(p+1,p+n+1,cmp); for (int i=1,pre=0;i<=n;++i) { int x=p[i]; for (int j=0;j<sz(G[x]);++j) { int to=G[x][j]; if (to!=fa[x]) { ans+=(ll)BIT::query(dfn[to],dfn[to]+sz[to]-1)*(n-sz[to]); } else { ans+=(ll)(BIT::query(1,n)-BIT::query(dfn[x],dfn[x]+sz[x]-1))*sz[x]; } } if (a[p[i]]==a[p[i+1]]) continue; for (int j=pre+1;j<=i;++j) { BIT::update(dfn[p[j]],1); } pre=i; } printf("%lld\n",ans); } int main() { init(); solve(); return 0; }