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
",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
",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
",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
",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
");
        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
",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)
",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
",ans);
}
 
int main()
{
    init();
    solve();
    return 0;
}
原文地址:https://www.cnblogs.com/huangchenyan/p/13324641.html