模板(按照洛谷顺序)

对拍(详见注释)

 1 #include<stdio.h>
 2 #include<windows.h>
 3 using namespace std;
 4 int main()
 5 {
 6     int n=100000;
 7     while(n--)
 8     {
 9         system("data.exe>data.in");//运行data.exe导入data.in 
10         system("myCode.exe<data.in>myCode.out");//用data.in的数据运行待测程序导入out文件
11         system("correctCode.exe<data.in>correctCode.out");//用data.in的数据运行对拍程序导入out文件
12         if(system("fc myCode.out correctCode.out")) break;//比较输出结果
13     }
14     system("pause");
15     return 0;
16 }
show you the code

负环

(spfa中一个点被松弛(放入队列中)n次,一定有负环)

 1 #include<bits/stdc++.h>
 2 #define I inline
 3 using namespace std;
 4 using namespace std;
 5 const int N=2010;
 6 const int M=3010;
 7 I int read()
 8 {
 9     int x=0,f=1;char ch=getchar();
10     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
11     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
12     return x*f;
13 }
14 
15 struct node
16 {
17     int nxt,to,dis;
18 }g[M<<1];
19 int head[N],tot;
20 int T,n,m;
21 int dist[N],cnt[N];
22 bool vis[N];
23 
24 I void addedge(int u,int v,int dis)
25 {
26     g[++tot].nxt=head[u];
27     g[tot].to=v;
28     g[tot].dis=dis;
29     head[u]=tot;
30 }
31 
32 I bool spfa()
33 {
34     memset(vis,0,sizeof(vis));
35     memset(cnt,0,sizeof(cnt));
36     memset(dist,127,sizeof(dist));
37     queue<int>q;q.push(1);vis[1]=0;dist[1]=0;
38     while(q.size())
39     {
40         int u=q.front();q.pop();vis[u]=0;
41         for(int i=head[u];i;i=g[i].nxt)
42         {
43             int v=g[i].to;
44             if(dist[v]>dist[u]+g[i].dis)
45             {
46                 cnt[v]=cnt[u]+1;
47                 if(cnt[v]>n)return 1;
48                 dist[v]=dist[u]+g[i].dis;
49                 if(!vis[v])vis[v]=1,q.push(v);
50             }
51         }
52     }
53     return 0;
54 }
55                 
56 
57 int main()
58 {
59     T=read();
60     while(T--)
61     {
62         n=read();m=read();tot=0;
63         memset(head,0,sizeof(head));
64         for(int i=1;i<=m;i++)
65         {
66             int x=read(),y=read(),z=read();
67             if(z<0)addedge(x,y,z);
68             else addedge(y,x,z),addedge(x,y,z);
69         }
70         if(spfa())puts("YE5");
71         else puts("N0");
72     }
73 }
show you the code

缩点

(tarjan+toposort+dp基操)

 1 #include<bits/stdc++.h>
 2 #define I inline
 3 using namespace std;
 4 using namespace std;
 5 const int N=1e4+10;
 6 const int M=1e5+10;
 7 I int read()
 8 {
 9     int x=0,f=1;char ch=getchar();
10     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
11     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
12     return x*f;
13 }
14 int n,m;
15 int val[N];
16 vector<int>g[N],e[N];
17 int dfn[N],low[N],sta[N],col[N],color,ind,top;
18 int p[N],in[N],dp[N],ans;
19 
20 I void tarjan(int u)
21 {
22     low[u]=dfn[u]=++ind;
23     sta[++top]=u;
24     for(int i=0;i<g[u].size();i++)
25     {
26         int v=g[u][i];
27         if(!dfn[v])tarjan(v),low[u]=min(low[u],low[v]);
28         else if(!col[v])low[u]=min(low[u],dfn[v]);
29     }
30     if(low[u]==dfn[u])
31     {
32         color++;
33         while(sta[top]!=u)
34         {
35             col[sta[top]]=color;
36             p[color]+=val[sta[top]];
37             top--;
38         }top--;col[u]=color;
39         p[color]+=val[u];
40     }
41 }
42 
43 I void topo()
44 {
45     queue<int>q;
46     for(int i=1;i<=color;i++)
47     {
48         if(!in[i])q.push(i),dp[i]=p[i];
49     }
50     while(!q.empty())
51     {
52         int u=q.front();q.pop();ans=max(ans,dp[u]);
53         for(int i=0;i<e[u].size();i++)
54         {
55             int v=e[u][i];
56             in[v]--;dp[v]=max(dp[v],dp[u]+p[v]);
57             if(!in[v])q.push(v);
58         }
59     }
60     cout<<ans;
61 }
62 
63 int main()
64 {
65     n=read();m=read();for(int i=1;i<=n;i++)val[i]=read();
66     for(int i=1;i<=m;i++)
67     {
68         int x=read(),y=read();
69         g[x].push_back(y);
70     }
71     for(int i=1;i<=n;i++)if(!dfn[i])tarjan(i);
72     for(int u=1;u<=n;u++)
73     for(int i=0;i<g[u].size();i++)
74     {
75         int v=g[u][i];
76         if(col[v]!=col[u])
77         {
78             e[col[u]].push_back(col[v]);
79             in[col[v]]++;
80         }
81     }
82     topo();
83 }
show you the code

ST表

(注意边界是$l+2^{k}-1$,询问的时候右边区间从$r-2^{k}+1$开始,即找一个x使$x+x^{k}-1=r$

 1 #include<bits/stdc++.h>
 2 #define I inline
 3 using namespace std;
 4 using namespace std;
 5 const int N=1e5+10;
 6 const int M=1e6+10;
 7 I int read()
 8 {
 9     int x=0,f=1;char ch=getchar();
10     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
11     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
12     return x*f;
13 }
14 int n,m;
15 int f[N][25];
16 
17 I void ST()
18 {
19     for(int j=1;(1<<j)-1<=n;j++)
20     for(int i=1;i+(1<<j)-1<=n;i++)
21     f[i][j]=max(f[i][j-1],f[i+(1<<j-1)][j-1]);
22 }
23 
24 I int query(int l,int r)
25 {
26     int k=log2(r-l+1);
27     return max(f[l][k],f[r-(1<<k)+1][k]);
28 }
29  
30 int main()
31 {
32     n=read();m=read();for(int i=1;i<=n;i++)f[i][0]=read();
33     ST();
34     while(m--)
35     {
36         int l=read(),r=read();
37         printf("%d
",query(l,r));
38     }
39 }
show you the code

动态DP

(NOIP2018毒瘤,求树上最大带权独立集,树形DP之后,先把dp值放到数组里,全部是虚边(每个点一棵splay根),修改用$max$矩阵乘法和LCT维护,注意一下pushup的时候矩阵乘法的和深度的关系,按照$ls(x)*x*rs(x)$的顺序乘)

  1 #include<cstdio>
  2 #include<algorithm>
  3 #include<cstring>
  4 #include<algorithm>
  5 #define I inline
  6 #define R register
  7 #define ls(x) ch[x][0]
  8 #define rs(x) ch[x][1]
  9 using namespace std;
 10 typedef long long LL;
 11 const int N=500010;
 12 const int inf=(1<<31)-1;
 13 
 14 I int read()
 15 {
 16     int x=0,f=1;char ch=getchar();
 17     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
 18     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
 19     return x*f;
 20 }
 21 
 22 int n,m;
 23 struct node
 24 {
 25     int nxt,to;
 26 }g[N<<1];
 27 int head[N],cnt;
 28 
 29 int a[N],f[N],ch[N][2];
 30 LL dp[N][2];
 31 
 32 struct matrix
 33 {
 34     LL p[2][2];
 35     matrix(){p[0][0]=p[0][1]=p[1][0]=p[1][1]=-inf;}//新定义的矩阵乘初始化    
 36 }s[N],si[N];//s为整棵splay(实链)上点的矩阵乘积
 37 //si为x的虚子树的矩阵乘积(包括自己) 
 38 
 39 I matrix operator * (const matrix &a,const matrix &b)
 40 {
 41     matrix c;
 42     for(int i=0;i<=1;i++)
 43     for(int k=0;k<=1;k++)
 44     for(int j=0;j<=1;j++)
 45     c.p[i][j]=max(c.p[i][j],a.p[i][k]+b.p[k][j]);
 46     return c;
 47 }
 48 
 49 I void dfs(R int u)//刚开始全部是虚边,所以不区分虚实子树 
 50 {
 51     dp[u][1]=a[u];
 52     for(int i=head[u];i;i=g[i].nxt)
 53     {
 54         int v=g[i].to;
 55         if(v==f[u])continue;
 56         f[v]=u;dfs(v);
 57         dp[u][0]+=max(dp[v][0],dp[v][1]);
 58         dp[u][1]+=dp[v][0];        
 59     }
 60     si[u].p[0][0]=si[u].p[0][1]=dp[u][0];
 61     si[u].p[1][0]=dp[u][1];
 62     s[u]=si[u];//开始s和si都一样 
 63 }
 64 
 65 I void pushup(R int x)
 66 {
 67     s[x]=si[x];//考虑推出的矩阵式子,其实就是
 68     //虚子树*dep小于dep[x]的和dep>dep[x]的实链上的,就是整棵树的贡献 
 69     if(ls(x))s[x]=s[ls(x)]*s[x];
 70     if(rs(x))s[x]=s[x]*s[rs(x)];
 71 }
 72 //一下为LCT板子,不需要link也不要cut也不要makeroot 
 73 I bool nroot(int x)
 74 {
 75     return ls(f[x])==x||rs(f[x])==x;
 76 }
 77 
 78 I void rotate(R int x)
 79 {
 80     int y=f[x],z=f[y],k=(rs(y)==x),w=ch[x][!k];
 81     if(nroot(y))ch[z][rs(z)==y]=x;ch[x][!k]=y;ch[y][k]=w;
 82     if(w)f[w]=y;f[x]=z;f[y]=x;pushup(y);pushup(x);
 83 }
 84 
 85 I void splay(R int x)
 86 {
 87     while(nroot(x))
 88     {
 89         int y=f[x],z=f[y];
 90         if(nroot(y))rotate((ls(y)==x)^(ls(z)==y)?x:y);
 91         rotate(x);
 92     }
 93 }    
 94 //这其实就是维护虚子树信息的access写法 
 95 I void access(R int x)
 96 {
 97     for(int y=0;x;x=f[y=x])
 98     {
 99         splay(x);
100         if(rs(x))//实变虚,加到虚树中 
101         {
102             si[x].p[0][0]+=max(s[rs(x)].p[0][0],s[rs(x)].p[1][0]);
103             si[x].p[1][0]+=s[rs(x)].p[0][0];
104         }
105         rs(x)=y;
106         if(rs(x))//虚变实,从虚树中减去 
107         {
108             si[x].p[0][0]-=max(s[rs(x)].p[0][0],s[rs(x)].p[1][0]);
109             si[x].p[1][0]-=s[rs(x)].p[0][0];
110         }si[x].p[0][1]=si[x].p[0][0];
111         pushup(x);//别忘了更新 
112     }
113 }
114 
115 I void modify(int x,int y)//很显然的修改函数 
116 {
117     access(x);splay(x);
118     si[x].p[1][0]-=a[x]-y;//转到splay的根上,照着dp方程直接修改即可 
119     a[x]=y;pushup(x);
120 }
121 
122 I void addedge(int u,int v)
123 {
124     g[++cnt].nxt=head[u];
125     g[cnt].to=v;head[u]=cnt;
126 }
127 
128 int main()
129 {
130     n=read();m=read();
131     for(int i=1;i<=n;i++)a[i]=read();
132     for(int i=1;i<n;i++)
133     {
134         int x=read(),y=read();
135         addedge(x,y);addedge(y,x);
136     }
137     dfs(1);
138     while(m--)
139     {
140         int x=read(),y=read();
141         modify(x,y);splay(1);//选一个点为根输出答案 
142         printf("%lld
",max(s[1].p[0][0],s[1].p[1][0]));
143     }
144 }
show you the code

线性求逆元

(记住就行了,从$p=k*i+r≡0(mod p)$开始推,乘一个$i^{-1}$和$r^{-1}$即可

 1 #include<bits/stdc++.h>
 2 #define I inline
 3 using namespace std;
 4 using namespace std;
 5 const int N=3e6+10;
 6 I int read()
 7 {
 8     int x=0,f=1;char ch=getchar();
 9     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
10     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
11     return x*f;
12 }
13 int n;
14 int p,inv[N];
15 
16 int main()
17 {
18     n=read();p=read();
19     inv[1]=1;
20     for(int i=2;i<=n;i++)
21     inv[i]=1LL*(p-p/i)*(inv[p%i])%p;
22     for(int i=1;i<=n;i++)printf("%d
",inv[i]);
23 }
show you the code

康拓展开

(就是给你一个$1-n$的排列,问你按字典序是$1-n$全排列的第几个(注意是否从$0$开始计算)$ans=(1+)sumlimits_{i=1}^na_i*(n-i)!$ 

 1 #include<bits/stdc++.h>
 2 #define lowbit(x) (x&-x)
 3 #define I inline
 4 using namespace std;
 5 using namespace std;
 6 const int N=1000010;
 7 const int p=998244353;
 8 I int read()
 9 {
10     int x=0,f=1;char ch=getchar();
11     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
12     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
13     return x*f;
14 }
15 int n,a[N],ans;
16 int bit[N],fac[N];
17 
18 I void add(int pos,int val)
19 {
20     while(pos<=n)bit[pos]+=val,pos+=lowbit(pos);
21 }
22 I int query(int pos)
23 {
24     int res=0;
25     while(pos)res+=bit[pos],pos-=lowbit(pos);
26     return res;
27 }
28 
29 int main()
30 {
31     n=read();for(int i=1;i<=n;i++)a[i]=read();
32     fac[0]=1;
33     for(int i=1;i<=n;i++)add(i,1),fac[i]=1LL*i*fac[i-1]%p;
34     for(int i=1;i<=n;i++)
35     {
36         int k=query(a[i])-1;
37         ans=(ans+1LL*k*fac[n-i]%p)%p;
38         add(a[i],-1);
39     }
40     cout<<ans+1;
41 }
show you the code

 线段树1

没啥可说的

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<algorithm>
  4 using namespace std;
  5 #define smid ((l+r)>>1)
  6 #define lch (now<<1)
  7 #define rch ((now<<1)|1)
  8 #define maxn 100005
  9 #define maxlen maxn*4
 10 #define root 1
 11 struct Sgt
 12 {long long num,pls;}sgt[maxlen];
 13 int n,m;
 14 long long a[maxn];
 15 void update(int now)
 16 {
 17     sgt[now].num=sgt[lch].num+sgt[rch].num;
 18 }
 19 void pushdown(int now,int l,int r)
 20 {
 21     if(sgt[now].pls)
 22     {
 23         sgt[lch].pls+=sgt[now].pls;
 24         sgt[lch].num+=(smid-l+1)*sgt[now].pls;
 25         sgt[rch].num+=(r-(smid+1)+1)*sgt[now].pls;
 26         sgt[rch].pls+=sgt[now].pls;
 27         sgt[now].pls=0;
 28     }
 29 }
 30 void build_sgt(int now,int l,int r)
 31 {
 32     if(l==r)
 33     {
 34         sgt[now].num=a[l];return ;
 35         }
 36         build_sgt(lch,l,smid);
 37         build_sgt(rch,smid+1,r);
 38         update(now);
 39     }
 40 void plus_sgt(int now,int l,int r,int x,int y,long long  val)
 41 {
 42     if(l==x&&r==y)
 43     {
 44         sgt[now].num+=(y-x+1)*val;
 45         sgt[now].pls+=val;
 46         return ;
 47     }
 48     pushdown(now,l,r);
 49     if(y<=smid)
 50     {
 51         plus_sgt(lch,l,smid,x,y,val);
 52     }
 53     else if(x>smid)
 54     {
 55         plus_sgt(rch,smid+1,r,x,y,val);
 56     }
 57     else
 58     {
 59         plus_sgt(lch,l,smid,x,smid,val);
 60         plus_sgt(rch,smid+1,r,smid+1,y,val);
 61     }
 62     update(now);
 63 }
 64 long long qry_sgt(int now,int l,int r,int x,int y)
 65 {
 66     if(l==x&&r==y)
 67     {
 68         return sgt[now].num;
 69     }
 70     pushdown(now,l,r);
 71     if(y<=smid)
 72     return qry_sgt(lch,l,smid,x,y);
 73     else if(x>smid)
 74     return qry_sgt(rch,smid+1,r,x,y);
 75     else
 76     return qry_sgt(lch,l,smid,x,smid)+qry_sgt(rch,smid+1,r,smid+1,y);
 77 }
 78 int main()
 79 {
 80     cin>>n>>m;
 81     for(int i=1;i<=n;i++)
 82     {
 83         scanf("%lld",&a[i]);
 84         }
 85         build_sgt(root,1,n);
 86         for(int i=1;i<=m;i++)
 87         {
 88             int cid;
 89             scanf("%d",&cid);
 90             if(cid==1)
 91             {
 92                 int x,y;
 93                 long long k;
 94                 scanf("%d%d%lld",&x,&y,&k);
 95                 plus_sgt(root,1,n,x,y,k);
 96             }    
 97             if(cid==2)
 98             {
 99                 int x,y;
100                 scanf("%d%d",&x,&y);
101                 printf("%lld
",qry_sgt(root,1,n,x,y));
102             }
103         }
104     }
show you the code

线段树2

注意下放标记的顺序即可,当然线段树的板子不止于此

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define root 1
#define lch now*2
#define rch now*2+1
#define smid (l+r)/2
using namespace std;
typedef long long LL;
const int maxn=100005;

int n,m,p;
struct node
{
    LL pls,mul,sum;
}sgt[maxn*4];
LL a[maxn];

void update(int now)
{
    sgt[now].sum=(sgt[lch].sum+sgt[rch].sum)%p;
}

void pushdown(int now,int l,int r)
{
    sgt[lch].pls=(sgt[lch].pls*sgt[now].mul%p+sgt[now].pls)%p;
    sgt[rch].pls=(sgt[rch].pls*sgt[now].mul%p+sgt[now].pls)%p;
    sgt[lch].mul=(sgt[lch].mul*sgt[now].mul)%p;
    sgt[rch].mul=(sgt[rch].mul*sgt[now].mul)%p;
    sgt[lch].sum=(sgt[now].pls*(smid-l+1)%p+sgt[lch].sum*sgt[now].mul%p)%p;
    sgt[rch].sum=(sgt[now].pls*(r-smid)%p+sgt[rch].sum*sgt[now].mul%p)%p;
    sgt[now].pls=0;
    sgt[now].mul=1;
}

void build_sgt(int now,int l,int r)
{
    sgt[now].pls=0;
    sgt[now].mul=1;
    if(l==r)
    {
        sgt[now].sum=a[l];
        return;
    }
    build_sgt(lch,l,smid);
    build_sgt(rch,smid+1,r);
    update(now);
}

void plus_sgt(int now,int l,int r,int x,int y,LL val)
{
    
    if(l==x&&r==y)
    {
        sgt[now].pls=(sgt[now].pls+val)%p;
        sgt[now].sum=(sgt[now].sum+(r-l+1)%p*val%p)%p;
        return;
    }
    pushdown(now,l,r);
    if(y<=smid)
    plus_sgt(lch,l,smid,x,y,val);
    else if(x>smid)
    plus_sgt(rch,smid+1,r,x,y,val);
    else
    {
        plus_sgt(lch,l,smid,x,smid,val);
        plus_sgt(rch,smid+1,r,smid+1,y,val);
    }
    update(now);
}

void multipy_sgt(int now,int l,int r,int x,int y,LL val)
{
    if(l==x&&r==y)
    {
        sgt[now].sum=sgt[now].sum*val%p;
        sgt[now].mul=sgt[now].mul*val%p;
        sgt[now].pls=sgt[now].pls*val%p;
        return;
    }
    pushdown(now,l,r);
    if(y<=smid)
    multipy_sgt(lch,l,smid,x,y,val);
    else if(x>smid)
    multipy_sgt(rch,smid+1,r,x,y,val);
    else
    {
        multipy_sgt(lch,l,smid,x,smid,val);
        multipy_sgt(rch,smid+1,r,smid+1,y,val);
    }
    update(now);
}

LL query_sgt(int now,int l,int r,int x,int y)
{
    if(x==l&&r==y)
    return sgt[now].sum;
    pushdown(now,l,r);
    if(y<=smid)
    return query_sgt(lch,l,smid,x,y)%p;
    else if(x>smid)
    return query_sgt(rch,smid+1,r,x,y)%p;
    else
    {
        return (query_sgt(lch,l,smid,x,smid)%p+
        query_sgt(rch,smid+1,r,smid+1,y)%p)%p;
    }
}
    
int main()
{
    scanf("%d%d%d",&n,&m,&p);
    for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
    build_sgt(root,1,n);
    while(m--)
    {
        int cid;
        scanf("%d",&cid);
        if(cid==1)
        {
            int x,y;
            LL k;
            scanf("%d%d%lld",&x,&y,&k);
            multipy_sgt(root,1,n,x,y,k);
        }
        if(cid==2)
        {
            int x,y;
            LL k;
            scanf("%d%d%lld",&x,&y,&k);
            plus_sgt(root,1,n,x,y,k);
        }
        if(cid==3)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            printf("%lld
",query_sgt(root,1,n,x,y)%p);
        }
    }
}
show you the code

2-SAT

加边的时候多注意就行,至于构造方案,,,考的不多,主要是不太理解为什么取拓扑序大的就行了

 1 #include<bits/stdc++.h>
 2 #define I inline
 3 using namespace std;
 4 const int N=2000010;
 5 I int read()
 6 {
 7     int x=0,f=1;char ch=getchar();
 8     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
 9     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
10     return x*f;
11 }
12 vector<int>g[N];
13 int n,m;
14 I void add(int u,int v){g[u].push_back(v);}
15 int dfn[N],low[N],sta[N],col[N],color,ind,top;
16 
17 I void tarjan(int u)
18 {
19     low[u]=dfn[u]=++ind;sta[++top]=u;
20     for(int i=0;i<g[u].size();i++)
21     {
22         int v=g[u][i];
23         if(!dfn[v])tarjan(v),low[u]=min(low[u],low[v]);
24         else if(!col[v])low[u]=min(low[u],dfn[v]);
25     }
26     if(low[u]==dfn[u])
27     {
28         color++;
29         while(sta[top]!=u)
30         {
31             col[sta[top]]=color;
32             top--;
33         }top--;col[u]=color;        
34     }
35 }
36 
37 I bool chk()
38 {
39     for(int i=1;i<=n;i++)
40     if(col[i]==col[i+n])return 0;
41     return 1;
42 }
43 
44 int main()
45 {
46     n=read();m=read();
47     for(int i=1;i<=m;i++)
48     {
49         int a=read(),b=read(),c=read(),d=read();
50         if(b&&d)add(a,c+n),add(c,a+n);
51         if(!b&&d)add(a+n,c+n),add(c,a);
52         if(b&&!d)add(a,c),add(c+n,a+n);
53         if(!b&&!d)add(a+n,c),add(c+n,a);
54     }
55     for(int i=1;i<=(n<<1);i++)if(!dfn[i])tarjan(i);
56     if(chk())
57     {
58         puts("POSSIBLE");
59         for(int i=1;i<=n;i++)
60         {
61             printf("%d ",col[i]>col[i+n]);
62         }
63         return 0;
64     }
65     cout<<"IMPOSSIBLE";
66     return 0;
67 }
show you the code

 三分

求单峰函数极值

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const double eps=1e-8;
 4 int n;
 5 double a[20],l,r;
 6 
 7 double val(double x)
 8 {
 9     double res=0;int v=0;
10     for(int i=n+1;i>=1;i--)res+=a[++v]*pow(x,i-1);
11     return res;
12 }
13 
14 int main()
15 {
16     cin>>n>>l>>r;
17     for(int i=1;i<=n+1;i++)cin>>a[i];
18     while(r-l>eps)
19     {
20         double m1=l+(r-l)/3.0,m2=r-(r-l)/3.0;
21         if(val(m1)-val(m2)>eps)r=m2;
22         else l=m1;
23     }
24     printf("%.5lf",l);
25 }
show you the code

 割点

判断$low[v]>=dfn[u]$

 1 #include<bits/stdc++.h>
 2 #define I inline
 3 using namespace std;
 4 const int N=20010;
 5 const int M=100010;
 6 I int read()
 7 {
 8     int x=0,f=1;char ch=getchar();
 9     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
10     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
11     return x*f;
12 }
13 
14 int n,m;
15 vector<int>g[N];
16 bool cut[N];
17 int ans;
18 int dfn[N],low[N],ind;
19 
20 I void tarjan(int u,int rt)
21 {
22     int ch=0;
23     low[u]=dfn[u]=++ind;
24     for(int i=0;i<g[u].size();i++)
25     {
26         int v=g[u][i];
27         if(!dfn[v])
28         {
29             tarjan(v,rt);
30             low[u]=min(low[u],low[v]);
31             if(u!=rt&&low[v]>=dfn[u])cut[u]=1;
32             if(u==rt)ch++;
33         }
34         low[u]=min(low[u],dfn[v]);
35     }
36     if(ch>=2&&u==rt)cut[u]=1;
37 }
38     
39 int main()
40 {
41     n=read();m=read();
42     for(int i=1;i<=m;i++)
43     {
44         int x=read(),y=read();
45         g[x].push_back(y);
46         g[y].push_back(x);
47     }
48     for(int i=1;i<=n;i++)if(!dfn[i])tarjan(i,i);    
49     for(int i=1;i<=n;i++)if(cut[i])ans++;
50     cout<<ans<<endl;
51     for(int i=1;i<=n;i++)if(cut[i])printf("%d ",i);
52 }
show you the code

树链剖分

 挑战30min打出树剖板子成功

  1 #include<bits/stdc++.h>
  2 #define I inline
  3 #define ls (now<<1)
  4 #define rs (now<<1|1)
  5 #define smid (l+r>>1)
  6 using namespace std;
  7 const int N=1e5+10;
  8 I int read()
  9 {
 10     int x=0,f=1;char ch=getchar();
 11     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
 12     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
 13     return x*f;
 14 }
 15 struct segment
 16 {
 17     int sum,pls;
 18 }sgt[N<<2];
 19 int n,m,rt,p;
 20 vector<int>g[N];
 21 int a[N];
 22 int dep[N],f[N],rk[N],id[N],ind,top[N],son[N],sz[N];
 23 
 24 I void dfs1(int u)
 25 {
 26     dep[u]=dep[f[u]]+1;
 27     sz[u]=1;
 28     for(int i=0;i<g[u].size();i++)
 29     {
 30         int v=g[u][i];
 31         if(v==f[u])continue;
 32         f[v]=u;dfs1(v);
 33         sz[u]+=sz[v];
 34         if(sz[v]>sz[son[u]])son[u]=v;
 35     }
 36 }
 37 
 38 I void dfs2(int u,int tp)
 39 {
 40     top[u]=tp;
 41     rk[++ind]=u;
 42     id[u]=ind;
 43     if(son[u])dfs2(son[u],tp);
 44     for(int i=0;i<g[u].size();i++)
 45     {
 46         int v=g[u][i];
 47         if(v==f[u]||v==son[u])continue;
 48         dfs2(v,v);
 49     }
 50 }
 51 
 52 I void pushup(int now)
 53 {
 54     sgt[now].sum=sgt[ls].sum+sgt[rs].sum;
 55 }
 56 
 57 I void pushdown(int now,int l,int r)
 58 {
 59     if(!sgt[now].pls)return;
 60     sgt[ls].pls=(sgt[ls].pls+sgt[now].pls)%p;
 61     sgt[rs].pls=(sgt[rs].pls+sgt[now].pls)%p;
 62     sgt[ls].sum=(sgt[ls].sum+1LL*(smid-l+1)*sgt[now].pls%p)%p;
 63     sgt[rs].sum=(sgt[rs].sum+1LL*(r-smid)*sgt[now].pls%p)%p;
 64     sgt[now].pls=0;
 65 }
 66 
 67 I void bt(int now,int l,int r)
 68 {
 69     if(l==r){sgt[now].sum=a[rk[l]];return ;}
 70     bt(ls,l,smid);bt(rs,smid+1,r);
 71     pushup(now);
 72 }
 73 
 74 I void modify(int now,int l,int r,int x,int y,int k)
 75 {
 76     if(x<=l&&r<=y)
 77     {
 78         sgt[now].sum=(sgt[now].sum+1LL*(r-l+1)*k%p)%p;
 79         sgt[now].pls=(sgt[now].pls+k)%p;
 80         return ;
 81     }
 82     pushdown(now,l,r);
 83     if(x<=smid)modify(ls,l,smid,x,y,k);
 84     if(smid<y)modify(rs,smid+1,r,x,y,k);
 85     pushup(now);
 86 }
 87 
 88 I int query(int now,int l,int r,int x,int y)
 89 {
 90     if(x<=l&&r<=y)return sgt[now].sum;
 91     pushdown(now,l,r);
 92     int res=0;
 93     if(x<=smid)res=(res+query(ls,l,smid,x,y))%p;
 94     if(smid<y)res=(res+query(rs,smid+1,r,x,y))%p;
 95     return res;
 96 }
 97 
 98 I void change_range(int x,int y,int z)
 99 {
100     while(top[x]!=top[y])
101     {
102         if(dep[top[x]]<dep[top[y]])swap(x,y);
103         modify(1,1,n,id[top[x]],id[x],z);
104         x=f[top[x]];
105     }
106     if(dep[x]<dep[y])swap(x,y);
107     modify(1,1,n,id[y],id[x],z);
108 }
109 
110 I int query_range(int x,int y)
111 {
112     int res=0;
113     while(top[x]!=top[y])
114     {
115         if(dep[top[x]]<dep[top[y]])swap(x,y);
116         res=(res+query(1,1,n,id[top[x]],id[x]))%p;
117         x=f[top[x]];
118     }
119     if(dep[x]<dep[y])swap(x,y);
120     res=(res+query(1,1,n,id[y],id[x]))%p;
121     return res;
122 }
123 
124 I void change_tree(int x,int z)
125 {
126     modify(1,1,n,id[x],id[x]+sz[x]-1,z);
127 }
128 
129 I int query_tree(int x)
130 {
131     return query(1,1,n,id[x],id[x]+sz[x]-1);
132 }
133 
134 int main()
135 {
136     n=read();m=read();rt=read();p=read();
137     for(int i=1;i<=n;i++)a[i]=read();
138     for(int i=1;i<n;i++)
139     {
140         int x=read(),y=read();
141         g[x].push_back(y);
142         g[y].push_back(x);
143     }
144     dfs1(rt);
145     dfs2(rt,rt);
146     bt(1,1,n);
147     while(m--)
148     {
149         int cid=read();
150         if(cid==1)
151         {
152             int x=read(),y=read(),z=read();
153             change_range(x,y,z);
154         }
155         if(cid==2)
156         {
157             int x=read(),y=read();
158             printf("%d
",query_range(x,y)%p);
159         }
160         if(cid==3)
161         {
162             int x=read(),z=read();
163             change_tree(x,z);
164         }
165         if(cid==4)
166         {
167             int x=read();
168             printf("%d
",query_tree(x))%p;
169         }
170     }
171 }
show you the code

 树状数组1

没啥可说的

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 using namespace std;
 5 #define lowbit(pos) ((pos)&(-pos))
 6 #define maxn 500005
 7 int tarr[maxn];
 8 int n,m;
 9 void addtarr(int pos,int k)
10 {
11     while(pos<maxn)
12     {
13         tarr[pos]+=k;
14         pos+=lowbit(pos);
15     }
16 }
17 int qrytarr(int pos)
18 {
19     int res=0;
20     while(pos)
21     {
22         res+=tarr[pos];
23         pos-=lowbit(pos);
24     }
25     return res;
26 }
27 int main()
28 {
29     scanf("%d%d",&n,&m);
30     for(int i=1;i<=n;i++)
31     {int p;scanf("%d",&p);addtarr(i,p);}
32     for(int i=1;i<=m;i++)
33     {
34         int cid;
35         int x;
36         scanf("%d",&cid);
37         if(cid==1)
38         {
39             int x,k;
40             scanf("%d%d",&x,&k);
41             addtarr(x,k);
42         }
43         else
44         {
45             int j,y;
46             scanf("%d%d",&j,&y);
47             printf("%d
",qrytarr(y)-qrytarr(j-1));
48         }
49     }
50 }
show you the code

树状数组2

差分一下就行了

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<iostream>
 4 using namespace std;
 5 #define maxn 500005
 6 #define lowbit(x) (x)&(-x)
 7 int tarr[maxn];
 8 int n,m;
 9 int in[maxn];
10 void addtarr(int pos,int v)
11 {
12     while(pos<=maxn)
13     {
14         tarr[pos]+=v;
15         pos+=lowbit(pos);}
16     }
17     int qrytarr(int pos)
18     {
19         int res=0;
20         while(pos)
21     {
22         res+=tarr[pos];
23         pos-=lowbit(pos);}
24         return res;
25     }
26 int main()
27 {
28     scanf("%d%d",&n,&m);
29     for(int i=1;i<=n;i++)
30     {
31         int x;
32         scanf("%d",&in[i]);}
33         for(int i=1;i<=n;i++)
34         {addtarr(i,in[i]-in[i-1]);}
35         //for(int s=1;s<=n;s++)
36         //{cout<<tarr[s]<<" ";}
37         //cout<<endl;
38         for(int i=1;i<=m;i++)
39         {
40             int cid;
41             scanf("%d",&cid);
42             if(cid==1)
43             {int x,y,k;
44             scanf("%d%d%d",&x,&y,&k);
45             addtarr(x,k);
46             addtarr(y+1,-k);
47         }
48         if(cid==2)
49         {
50             int x;
51             scanf("%d",&x);
52             printf("%d
",qrytarr(x));
53         }
54     }
55 }            
show you the code

普通平衡树(fhq Treap)

记得画图模拟split和merge,merge时按照rank,split时按照val

  1 #include<bits/stdc++.h>
  2 #define ls(x) ch[x][0]
  3 #define rs(x) ch[x][1]
  4 #define I inline
  5 using namespace std;
  6 const int N=100010;
  7 I int read()
  8 {
  9     int x=0,f=1;char ch=getchar();
 10     while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
 11     while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
 12     return x*f;
 13 }
 14 
 15 int ch[N][2],rnk[N],val[N],sz[N],root,x,y,z,cnt;
 16 int n;
 17 
 18 I void pushup(int now)
 19 {
 20     sz[now]=sz[ls(now)]+sz[rs(now)]+1;
 21 }
 22 
 23 I void split(int now,int k,int &x,int &y)
 24 {
 25     if(!now)x=y=0;
 26     else 
 27     {
 28         if(val[now]<=k)x=now,split(rs(now),k,rs(now),y);
 29         else y=now,split(ls(now),k,x,ls(now));
 30         pushup(now);
 31     }
 32 }
 33 
 34 I int merge(int x,int y)
 35 {
 36     if(!x||!y)return x+y;
 37     if(rnk[x]<rnk[y]){rs(x)=merge(rs(x),y);pushup(x);return x;}
 38     else{ls(y)=merge(x,ls(y));pushup(y);return y;}
 39 }
 40 
 41 I int kth(int now,int k)
 42 {
 43     while(1)
 44     {
 45         if(k<=sz[ls(now)])now=ls(now);
 46         else if(k==sz[ls(now)]+1)return now;
 47         else k-=sz[ls(now)]+1,now=rs(now);
 48     }
 49 }
 50 
 51 I int new_node(int x)
 52 {
 53     cnt++;sz[cnt]=1;
 54     val[cnt]=x;rnk[cnt]=rand();
 55     return cnt;
 56 }
 57 
 58 I void insert(int k)
 59 {
 60     split(root,k,x,y);
 61     root=merge(merge(x,new_node(k)),y);
 62 }
 63 
 64 I void del(int k)
 65 {
 66     split(root,k,x,z);
 67     split(x,k-1,x,y);
 68     y=merge(ls(y),rs(y));
 69     root=merge(merge(x,y),z);
 70 }
 71 
 72 I int getrank(int k)
 73 {
 74     split(root,k-1,x,y);
 75     printf("%d
",sz[x]+1); 
 76     root=merge(x,y);
 77 }
 78 
 79 I int get_pre(int k)
 80 {
 81     split(root,k-1,x,y);
 82     printf("%d
",val[kth(x,sz[x])]);
 83     root=merge(x,y);
 84 }
 85 
 86 I int get_nxt(int k)
 87 {
 88     split(root,k,x,y);
 89     printf("%d
",val[kth(y,1)]);
 90     root=merge(x,y);
 91 }
 92 
 93 int main()
 94 {
 95     srand(time(0));
 96     n=read();
 97     while(n--)
 98     {
 99         int op=read(),k=read();
100         if(op==1)insert(k);
101         if(op==2)del(k);
102         if(op==3)getrank(k);
103         if(op==4)printf("%d
",val[kth(root,k)]);
104         if(op==5)get_pre(k);
105         if(op==6)get_nxt(k);
106     }
107 }
show you the code

矩阵快速幂

记得精度,重载比较美观,记得单位矩阵

 1 #include<bits/stdc++.h>
 2 #define ls(x) ch[x][0]
 3 #define rs(x) ch[x][1]
 4 #define I inline
 5 using namespace std;
 6 const int N=110;
 7 const int p=1e9+7;
 8 typedef long long LL;
 9 struct mat
10 {
11     LL p[N][N];
12 }base,ans,a;
13 
14 int n;
15 LL k;
16 
17 mat operator * (mat a,mat b)
18 {
19     mat c;
20     for(int i=1;i<=n;i++)
21     for(int j=1;j<=n;j++)
22     c.p[i][j]=0;
23     
24     for(int i=1;i<=n;i++)
25     for(int k=1;k<=n;k++)
26     for(int j=1;j<=n;j++)
27     c.p[i][j]=(c.p[i][j]%p+a.p[i][k]*b.p[k][j]%p)%p;
28     return c;
29 }
30 
31 mat qpow(mat a,LL k)
32 {
33     for(int i=1;i<=n;i++)base.p[i][i]=1;
34     while(k)
35     {
36         if(k&1LL)base=base*a;
37         a=a*a;k>>=1LL;
38     }
39     return base;
40 }
41 
42 int main()
43 {
44     cin>>n>>k;
45     for(int i=1;i<=n;i++)
46     for(int j=1;j<=n;j++)
47     cin>>a.p[i][j];
48     ans=qpow(a,k);
49     for(int i=1;i<=n;i++)
50     {
51         for(int j=1;j<=n;j++)
52         printf("%lld ",ans.p[i][j]%p);
53         printf("
");
54     }
55 }
show you the code

 卢卡斯定理

模数p小的情况下用于求组合数。

公式 $C_m^n=C_{m/p}^{n/p}*C_{mmod p}^{nmod p}$

模运算直接算,除法运算递归即可。

 1 #include<bits/stdc++.h>
 2 #define I inline
 3 using namespace std;
 4 const int N=1e5+10;
 5 I int read()
 6 {
 7     int x=0,f=1;char ch=getchar();
 8     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
 9     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
10     return x*f;
11 }
12 int T,fac[N];
13 
14 I int ksm(int a,int b,int p)
15 {
16     int res=1;
17     while(b)
18     {
19         if(b&1)res=1LL*res*a%p;
20         a=1LL*a*a%p;
21         b>>=1;
22     }
23     return res;
24 }
25 
26 I int C(int n,int m,int p)
27 {
28     if(n<m)return 0;
29     return 1LL*fac[n]*ksm(fac[m],p-2,p)%p*1LL*ksm(fac[n-m],p-2,p)%p;
30 }
31 
32 I int Lucas(int n,int m,int p)
33 {
34     return !m?1:1LL*C(n%p,m%p,p)*Lucas(n/p,m/p,p)%p;
35 }
36 
37 int main()
38 {
39     T=read();
40     while(T--)
41     {
42         int n=read(),m=read(),p=read();
43         fac[0]=1;for(int i=1;i<=p;i++)fac[i]=1LL*fac[i-1]*i%p;
44         printf("%d
",Lucas(n+m,m,p));
45     }
46 }
show you the code

 线性筛素数

背掉,关键在于$imod prime[j]=0$时$i*prime[j]$可以被一个更小的质数和一个更大的合数表示

 1 #include<bits/stdc++.h>
 2 #define I inline
 3 using namespace std;
 4 const int N=10000010;
 5 int prime[N],cnt;
 6 bool not_prime[N];
 7 int n,m;
 8 
 9 I void pre()
10 {
11     not_prime[0]=not_prime[1]=1;
12     for(int i=2;i<=n;i++)
13     {
14         if(!not_prime[i])prime[++cnt]=i;
15         for(int j=1;j<=cnt&&prime[j]*i<=n;j++)
16         {
17             not_prime[prime[j]*i]=1;
18             if(i%prime[j]==0)break;
19         }
20     }
21 }
22 int main()
23 {
24     cin>>n>>m;
25     pre();
26     while(m--)
27     {
28         int x;scanf("%d",&x);
29         if(not_prime[x])puts("No");
30         else puts("Yes");
31     }
32 }
show you the code

 矩阵加速递推

注意细节,可以用初始矩阵开始乘,也可以用单位矩阵开始乘

 1 #include<bits/stdc++.h>
 2 #define I inline
 3 using namespace std;
 4 typedef long long LL;
 5 const int p=1e9+7;
 6 I int read()
 7 {
 8     int x=0,f=1;char ch=getchar();
 9     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
10     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
11     return x*f;
12 }
13 struct mat
14 {
15     LL p[5][5];
16 }base,ans;
17 int T;
18 
19 I mat operator * (mat a,mat b)
20 {
21     mat c;memset(c.p,0,sizeof(c.p));
22     for(int i=1;i<=3;i++)
23     for(int k=1;k<=3;k++)
24     for(int j=1;j<=3;j++)
25     c.p[i][j]=(c.p[i][j]%p+a.p[i][k]*b.p[k][j]%p)%p;
26     return c;
27 }
28 
29 void mat_ksm(int k)
30 {
31     memset(base.p,0,sizeof(base.p));
32     memset(ans.p,0,sizeof(ans.p));
33     base.p[1][1]=base.p[2][1]=base.p[1][3]=base.p[3][2]=1;
34     ans.p[1][1]=ans.p[2][1]=ans.p[3][1]=1;
35     while(k)
36     {
37         if(k&1)ans=ans*base;
38         base=base*base;
39         k>>=1;
40     }
41 }
42 
43 int main()
44 {
45     T=read();
46     while(T--)
47     {
48         int n=read();
49         if(n<=3)puts("1");
50         else
51         {
52             mat_ksm(n-1);
53             printf("%lld
",ans.p[1][1]);
54         }
55     }
56 }
show you the code

有理数取余(大数除法模运算)

$$cequivfrac{a}{b}pmod p$$

$$b*cequiv apmod p$$

$$b*(a*inv[b])equiv apmod p$$

$$b_{mod p}*a_{mod p}*inv[b]_{mod p}equiv a_{mod p}pmod p$$

$$c=a_{mod p}*inv[b]_{mod p}$$

求一下逆元就好了,这里因为有angry的情况,根据exgcd的成立条件特判即可。

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstdio>
 4 #include<cstring>
 5 #define LL long long
 6 using namespace std;
 7 const LL p=19260817;
 8 LL a,b;
 9 LL x,y;
10 inline LL read()
11 {
12     LL x=0,f=1;
13     char ch=getchar();
14     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
15     while(ch>='0'&&ch<='9')
16     {
17         x=(x*10%p+(ch-'0')%p)%p;ch=getchar();
18     }
19     return (x*f)%p;
20 }
21 LL exgcd(LL a,LL b,LL &x,LL &y)
22 {
23     if(b==0)
24     {
25         x=1;y=0;
26         return a;
27     }
28     LL k=exgcd(b,a%b,x,y);
29     LL t=x;
30     x=y;
31     y=t-(a/b)*y;
32     return k;
33 }
34 int main()
35 {
36     a=read();
37     b=read();
38     LL r=exgcd(b,p,x,y);
39     if(r!=1){cout<<"Angry!";return 0;}
40     x=(x%p+p)%p;
41     cout<<(x%p*a%p)%p;
42     return 0;
43 }
show you the code

二分图匹配

注意判vis,找当前点增光路的时候如果有环(之前被dfs的点又被找了一次)直接跳过

 1 #include<bits/stdc++.h>
 2 #define I inline
 3 using namespace std;
 4 const int N=1010;
 5 I int read()
 6 {
 7     int x=0,f=1;char ch=getchar();
 8     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
 9     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
10     return x*f;
11 }
12 int g[N][N];
13 int n,m,e;
14 int ans,match[N];
15 bool vis[N];
16 
17 I bool dfs(int u)
18 {
19     for(int v=1;v<=m;v++)
20     {
21         if(!vis[v]&&g[u][v])
22         {
23             vis[v]=1;
24             if(!match[v]||dfs(match[v]))
25             {
26                 match[v]=u;return 1;
27             }
28         }
29     }return 0;
30 }
31 
32 int main()
33 {
34     n=read();m=read();e=read();
35     for(int i=1;i<=e;i++)
36     {
37         int x=read(),y=read();
38         if(x<=n&&y<=m)g[x][y]=1;
39     }
40     for(int i=1;i<=n;i++)
41     {
42         memset(vis,0,sizeof(vis));
43         ans+=dfs(i);
44     }
45     cout<<ans;
46 }
show you the code

树上公共祖先(树剖求LCA)

 1 #include<bits/stdc++.h>
 2 #define I inline
 3 using namespace std;
 4 const int N=500010;
 5 I int read()
 6 {
 7     int x=0,f=1;char ch=getchar();
 8     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
 9     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
10     return x*f;
11 }
12 vector<int>g[N];
13 int n,m,rt;
14 int dep[N],son[N],sz[N],top[N],f[N];
15 
16 I void dfs1(int u)
17 {
18     dep[u]=dep[f[u]]+1;
19     sz[u]=1;
20     for(int i=0;i<g[u].size();i++)
21     {
22         int v=g[u][i];
23         if(v==f[u])continue;
24         f[v]=u;dfs1(v);
25         sz[u]+=sz[v];
26         if(sz[v]>sz[son[u]])son[u]=v;
27     }
28 }
29 
30 I void dfs2(int u,int tp)
31 {
32     top[u]=tp;if(son[u])dfs2(son[u],tp);
33     for(int i=0;i<g[u].size();i++)
34     {
35         int v=g[u][i];
36         if(v==f[u]||v==son[u])continue;
37         dfs2(v,v);
38     }
39 }
40 
41 I int LCA(int x,int y)
42 {
43     while(top[x]!=top[y])
44     {
45         if(dep[top[x]]<dep[top[y]])swap(x,y);
46         x=f[top[x]];
47     }
48     if(dep[x]<dep[y])swap(x,y);
49     return y;
50 }
51 
52 
53 int main()
54 {
55     n=read();m=read();rt=read();
56     for(int i=1;i<n;i++)
57     {
58         int x=read(),y=read();
59         g[x].push_back(y);
60         g[y].push_back(x);
61     }
62     dfs1(rt);dfs2(rt,rt);
63     while(m--)
64     {
65         int x=read(),y=read();
66         printf("%d
",LCA(x,y));
67     }
68 }
show you the code

 快速幂

不说什么。。。

 1 #include<bits/stdc++.h>
 2 #define I inline
 3 using namespace std;
 4 I int read()
 5 {
 6     int x=0,f=1;char ch=getchar();
 7     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
 8     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
 9     return x*f;
10 }
11 int b,k,p;
12 
13 I int ksm(int b,int k,int p)
14 {
15     int res=1;
16     while(k)
17     {
18         if(k&1)res=1LL*res*b%p;
19         b=1LL*b*b%p;k>>=1;
20     }
21     return res%p;
22 }
23 
24 int main()
25 {
26     b=read();k=read();p=read();
27     printf("%d^%d mod %d=%d",b,k,p,ksm(b,k,p));
28 }
show you the code

字符串匹配(KMP)

注意细节,预处理的时候从第2个开始更新,匹配串要和$i$之前的自我匹配,$while里的j>0$容易忘

 1 #include<bits/stdc++.h>
 2 #define I inline
 3 using namespace std;
 4 const int N=1000010;
 5 char a[N],b[N];
 6 int n,m,nxt[N];
 7 I void pre()
 8 {
 9     int j=0;nxt[1]=0;
10     for(int i=1;i<m;i++)
11     {
12         while(j&&b[j+1]!=b[i+1])j=nxt[j];
13         if(b[j+1]==b[i+1])j++;nxt[i+1]=j;
14     }
15 }
16 
17 I void kmp()
18 {
19     int j=0;
20     for(int i=0;i<n;i++)
21     {
22         while(j&&b[j+1]!=a[i+1])j=nxt[j];
23         if(b[j+1]==a[i+1])j++;
24         if(j==m)printf("%d
",i-m+2),j=nxt[j];
25     }
26 }
27 
28 int main()
29 {
30     cin>>a+1>>b+1;
31     n=strlen(a+1);m=strlen(b+1);
32     pre();kmp();
33     for(int i=1;i<=m;i++)printf("%d ",nxt[i]);
34 }
show you the code

 最小费用最大流(EK)

EK,把bfs换成spfa就行了

 1 #include<bits/stdc++.h>
 2 #define I inline
 3 using namespace std;
 4 const int N=5010;
 5 const int M=50010;
 6 const int inf=2147483647;
 7 I int read()
 8 {
 9     int x=0,f=1;char ch=getchar();
10     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
11     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
12     return x*f;
13 }
14 struct node
15 {
16     int nxt,to,w,f;
17 }g[M<<1];
18 struct PRE
19 {
20     int id,u;
21 }pre[N];
22 int dist[N];
23 bool vis[N];
24 int head[N],cnt=1;
25 int n,m,s,t;
26 int cost;
27 I void addedge(int u,int v,int w,int f)
28 {
29     g[++cnt].nxt=head[u];
30     g[cnt].to=v;
31     g[cnt].w=w;
32     g[cnt].f=f;
33     head[u]=cnt;
34 }
35 
36 I bool spfa()
37 {
38     for(int i=1;i<=n;i++)dist[i]=inf;
39     memset(vis,0,sizeof(vis));
40     memset(pre,-1,sizeof(pre));
41     queue<int>q;q.push(s);dist[s]=0;
42     while(!q.empty())
43     {
44         int u=q.front();q.pop();vis[u]=0;
45         for(int i=head[u];i;i=g[i].nxt)
46         {
47             int v=g[i].to,f=g[i].f,w=g[i].w;
48             if(w&&dist[v]>dist[u]+f)
49             {
50                 dist[v]=dist[u]+f;
51                 pre[v].u=u;pre[v].id=i;
52                 if(!vis[v])q.push(v),vis[v]=1;
53             }
54         }
55     }
56     return dist[t]!=inf;
57 }
58 
59 I int EK()
60 {
61     int maxflow=0;
62     while(spfa())
63     {
64         int mi=inf;
65         for(int i=t;i!=s;i=pre[i].u)mi=min(mi,g[pre[i].id].w);
66         for(int i=t;i!=s;i=pre[i].u)g[pre[i].id].w-=mi,g[pre[i].id^1].w+=mi;
67         maxflow+=mi;cost+=mi*dist[t];
68     }
69     return maxflow;
70 }
71 
72 int main()
73 {
74     n=read();m=read();s=read();t=read();
75     for(int i=1;i<=m;i++)
76     {
77         int x=read(),y=read(),w=read(),f=read();
78         addedge(x,y,w,f);addedge(y,x,0,-f);
79     }
80     printf("%d ",EK());printf("%d",cost);
81 }
show you the code

单源最短路径(dijkstra)

关于spfa,

它死了

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N=200010;
 4 struct node
 5 {
 6     int pos,dis;
 7     bool operator < (const node &x)const
 8     {
 9         return dis>x.dis;
10     }
11 };
12 priority_queue<node>q;
13 struct edge
14 {
15     int next,to,dis;
16 }g[N];
17 int head[N],cnt;
18 int n,m,s;
19 
20 inline void addedge(int u,int v,int dis)
21 {
22     g[++cnt].next=head[u];
23     g[cnt].to=v;
24     g[cnt].dis=dis;
25     head[u]=cnt;
26 }
27 
28 bool vis[maxn];
29 int dis[maxn];
30 
31 void dijkstra(int x)
32 {
33     for(int i=1;i<=n;i++)
34     {
35         dis[i]=2147483647;vis[i]=0;
36     }
37     q.push((node){x,0});
38     dis[x]=0;
39     while(!q.empty())
40     {
41         int u=q.top().pos;q.pop();
42         if(vis[u])continue;
43         vis[u]=1;
44         for(int i=head[u];i;i=g[i].next)
45         {
46             int v=g[i].to;
47             if(dis[v]>dis[u]+g[i].dis)
48             {
49                 dis[v]=dis[u]+g[i].dis;
50                 if(!vis[v])
51                 {
52                     q.push((node){v,dis[v]});
53                 }
54             }
55         }
56     }
57 }
58 int main()
59 {
60     scanf("%d%d%d",&n,&m,&s);
61     for(int i=1;i<=m;i++)
62     {
63         int x,y,z;
64         scanf("%d%d%d",&x,&y,&z);
65         addedge(x,y,z);
66     }
67     dijkstra(s);
68     for(int i=1;i<=n;i++)
69     {
70         cout<<dis[i]<<" ";
71     }
72 }
show you the code

 静态区间第k小(主席树)

自我感觉主席树写的挺美观qwq,注意时间关系,离散化下标,前缀和和线段树二分思想

 1 #include<bits/stdc++.h>
 2 #define smid (l+r>>1)
 3 #define I inline
 4 using namespace std;
 5 const int N=2e5+10;
 6 I int read()
 7 {
 8     int x=0,f=1;char ch=getchar();
 9     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
10     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
11     return x*f;
12 }
13 int sum[N<<5],ls[N<<5],rs[N<<5],T[N],cnt;
14 int n,m,d,a[N],b[N];
15 
16 I void bt(int &now,int l,int r)
17 {
18     now=++cnt;if(l==r)return;
19     bt(ls[now],l,smid);bt(rs[now],smid+1,r);
20 }
21 
22 I void modify(int &now,int pre,int l,int r,int pos)
23 {
24     now=++cnt;sum[now]=sum[pre]+1;ls[now]=ls[pre];rs[now]=rs[pre];
25     if(l==r)return;
26     if(pos<=smid)modify(ls[now],ls[pre],l,smid,pos);
27     else modify(rs[now],rs[pre],smid+1,r,pos);
28 }
29 
30 I int query(int now,int pre,int l,int r,int k)
31 {
32     if(l==r)return b[l];
33     int s=sum[ls[now]]-sum[ls[pre]];
34     if(s>=k)return query(ls[now],ls[pre],l,smid,k);
35     else return query(rs[now],rs[pre],smid+1,r,k-s);
36 }
37 
38 int main()
39 {
40     n=read();m=read();
41     for(int i=1;i<=n;i++)a[i]=read(),b[i]=a[i];
42     sort(b+1,b+1+n);d=unique(b+1,b+1+n)-b-1;
43     bt(T[0],1,d);
44     for(int i=1;i<=n;i++)
45     {
46         int x=lower_bound(b+1,b+1+d,a[i])-b;
47         modify(T[i],T[i-1],1,d,x);
48     }
49     while(m--)
50     {
51         int l=read(),r=read(),k=read();
52         printf("%d
",query(T[r],T[l-1],1,d,k));
53     }
54 }
show you the code

 左偏树

不太可能会考,不用$dsu$的版本很好写,如果加了$dsu$,注意一下$pop时f[ls[x]]=f[rs[x]]=f[x]=merge(ls[x],rs[x])$,因为并查集可能有多个儿子,并不是二叉树,所以要把其他儿子的根通过x也变成新的merge(ls[x],rs[x])(画个菊花图模拟一下就好啦)

 1 #include<bits/stdc++.h>
 2 #define I inline
 3 using namespace std;
 4 const int N=100010;
 5 I int read()
 6 {
 7     int x=0,f=1;char ch=getchar();
 8     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
 9     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
10     return x*f;
11 }
12 int n,m;
13 int f[N],val[N],ls[N],rs[N],dist[N];
14 
15 I int getf(int x){return x==f[x]?x:f[x]=getf(f[x]);}
16 
17 I int merge(int x,int y)
18 {
19     if(!x||!y)return x+y;
20     if(val[x]>val[y]||(val[x]==val[y]&&x>y))swap(x,y);
21     rs[x]=merge(rs[x],y);
22     f[rs[x]]=x;
23     if(dist[ls[x]]<dist[rs[x]])swap(ls[x],rs[x]);
24     dist[x]=dist[rs[x]]+1;
25     return x;
26 }
27 
28 I void pop(int x)
29 {
30     val[x]=-1;f[ls[x]]=f[rs[x]]=f[x]=merge(ls[x],rs[x]);
31 }
32 
33 int main()
34 {
35     n=read();m=read();for(int i=1;i<=n;i++)val[i]=read();
36     dist[0]=-1;for(int i=1;i<=n;i++)f[i]=i;
37     while(m--)
38     {
39         int cid=read();
40         if(cid==1)
41         {
42             int x=read(),y=read();
43             int r1=getf(x),r2=getf(y);
44             if(val[x]==-1||val[y]==-1)continue;
45             if(r1==r2)continue;
46             f[r1]=f[r2]=merge(r1,r2);
47         }
48         if(cid==2)
49         {
50             int x=read();
51             if(val[x]==-1){puts("-1");continue;}
52             int r=getf(x);printf("%d
",val[r]);
53             pop(r);
54         }
55     }
56 }
show you the code

LCT

注意画图模拟,,,顺序:$access->splay->rotate->nroot->pushup->pushdown->reverse->makeroot->link->split->cut$

注意修改点权时,要把点移动到splay的根,这样没有影响

 1 #include<bits/stdc++.h>
 2 #define ls(x) ch[x][0]
 3 #define rs(x) ch[x][1]
 4 #define I inline
 5 using namespace std;
 6 const int N=100010;
 7 I int read()
 8 {
 9     int x=0,f=1;char ch=getchar();
10     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
11     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
12     return x*f;
13 }
14 int n,m;
15 int val[N],sum[N],ch[N][2],f[N],sta[N];
16 bool rev[N];
17 
18 I void pushup(int x){sum[x]=val[x]^sum[ls(x)]^sum[rs(x)];}
19 
20 I bool nroot(int x){return ls(f[x])==x||rs(f[x])==x;}
21 
22 I void reverse(int x){rev[x]^=1;swap(ls(x),rs(x));}
23 
24 I void pushdown(int x)
25 {
26     if(!rev[x])return;
27     if(ls(x))reverse(ls(x));
28     if(rs(x))reverse(rs(x));
29     rev[x]=0;
30 }
31 
32 I void rotate(int x)
33 {
34     int y=f[x],z=f[y],k=rs(y)==x,w=ch[x][!k];
35     if(nroot(y))ch[z][rs(z)==y]=x;ch[x][!k]=y;ch[y][k]=w;
36     if(w)f[w]=y;f[x]=z;f[y]=x;pushup(y);
37 }
38 
39 I void splay(int x)
40 {
41     int y=x,z=1;sta[z]=y;
42     while(nroot(y))sta[++z]=y=f[y];
43     while(z)pushdown(sta[z--]);
44     while(nroot(x))
45     {
46         y=f[x];z=f[y];
47         if(nroot(y))rotate((ls(y)==x)^(ls(z)==y)?x:y);
48         rotate(x);
49     }pushup(x);
50 }
51 
52 I void access(int x)
53 {
54     for(int y=0;x;y=x,x=f[x])
55     splay(x),rs(x)=y,pushup(x);
56 }
57 
58 I int findroot(int x)
59 {
60     access(x);splay(x);
61     while(ls(x))pushdown(x),x=ls(x);
62     splay(x);
63     return x;
64 }
65 
66 I void makeroot(int x){access(x);splay(x);reverse(x);}
67 
68 I void link(int x,int y){makeroot(x);if(findroot(y)!=x)f[x]=y;}
69 
70 I void split(int x,int y){makeroot(x);access(y);splay(y);}
71 
72 I void cut(int x,int y)
73 {
74     makeroot(x);
75     if(findroot(y)==x&&f[y]==x&&!ls(y))f[y]=rs(x)=0,pushup(x);
76 }
77 
78 int main()
79 {
80     n=read();m=read();for(int i=1;i<=n;i++)val[i]=read();
81     while(m--)
82     {
83         int op=read(),x=read(),y=read();
84         if(op==0)split(x,y),printf("%d
",sum[y]);
85         if(op==1)link(x,y);
86         if(op==2)cut(x,y);
87         if(op==3)splay(x),val[x]=y;
88     }
89 }
show you the code

 欧拉路径(欧拉图的遍历)

从$degree$为奇数的点开始(由欧拉路径性质),每次遍历出边中序号字典序最小的点(题目要求),并把这条双向边删掉,用$stack$存一下即可

 1 #include <cstdio>
 2 #include <algorithm>
 3 #include <iostream>
 4 #include <stack>
 5 using namespace std;
 6 const int maxn = 1031;
 7 int G[maxn][maxn],du[maxn];
 8 int n,m;
 9 stack<int>S;
10 void dfs(int u)
11 {
12     for(int v=1;v<=n;v++)
13         if(G[u][v])
14         {
15             G[u][v]--;
16             G[v][u]--;
17             dfs(v);
18         }
19     S.push(u);
20 }
21 int main(){
22 
23     cin>>m;
24     int u,v;
25     for(int i=1;i<=m;i++){
26         cin>>u>>v;
27         n=max(n,u);
28         n=max(n,v); 
29         G[u][v]++;
30         G[v][u]++;
31         du[u]++;
32         du[v]++;
33     }
34     int s=1;
35     for(int i=1;i<=n;i++)
36         if(du[i]%2==1) 
37         {   
38             s=i;
39             break;
40         }
41     dfs(s);
42     while(!S.empty())
43     {
44         cout<<S.top()<<endl;
45         S.pop();
46     }
47     return 0;
48 }
show you the code

三维偏序(CDQ分治)

考虑两个排好序的序列合并,前面的对后面的做贡献

 1 #include<bits/stdc++.h>
 2 #define I inline
 3 #define lowbit(x) (x&-x)
 4 using namespace std;
 5 const int N=100010;
 6 I int read()
 7 {
 8     int x=0,f=1;char ch=getchar();
 9     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
10     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
11     return x*f;
12 }
13 
14 struct node
15 {
16     int a,b,c,f,w;
17 }q[N],t[N];
18 int ans[N];
19 int n,m;
20 int bit[N<<1];
21 
22 I void add(int pos,int val)
23 {
24     while(pos<=m)bit[pos]+=val,pos+=lowbit(pos);
25 }
26 I int query(int pos)
27 {
28     int res=0;
29     while(pos)res+=bit[pos],pos-=lowbit(pos);
30     return res;
31 }
32 
33 I bool cmp(node a,node b)
34 {
35     return a.a==b.a?(a.b==b.b?a.c<b.c:a.b<b.b):a.a<b.a;
36 }
37 
38 I void cdq(int l,int r)
39 {
40     if(l==r)return;
41     int mid=(l+r>>1);
42     cdq(l,mid);cdq(mid+1,r);
43     int i=l,j=mid+1,k=l;
44     while(i<=mid&&j<=r)
45     {
46         if(q[i].b<=q[j].b)add(q[i].c,q[i].w),t[k++]=q[i++];
47         else q[j].f+=query(q[j].c),t[k++]=q[j++];
48     }
49     while(i<=mid)add(q[i].c,q[i].w),t[k++]=q[i++];
50     while(j<=r)q[j].f+=query(q[j].c),t[k++]=q[j++];
51     for(i=l;i<=mid;i++)add(q[i].c,-q[i].w);
52     for(i=l;i<=r;i++)q[i]=t[i];
53 }
54 
55 int main()
56 {
57     n=read();m=read();
58     for(int i=1;i<=n;i++)
59     {
60         q[i].a=read();q[i].b=read();q[i].c=read();q[i].w=1;
61     }
62     sort(q+1,q+1+n,cmp);
63     int cnt=1;
64     for(int i=2;i<=n;i++)
65     {
66         if(q[cnt].a==q[i].a&&q[cnt].b==q[i].b&&q[cnt].c==q[i].c)q[cnt].w++;
67         else q[++cnt]=q[i];
68     }
69     cdq(1,cnt);
70     for(int i=1;i<=cnt;i++)ans[q[i].f+q[i].w-1]+=q[i].w;
71     for(int i=0;i<n;i++)printf("%d
",ans[i]);
72 }
show you the code

单调栈求最大子矩阵

维护$pre[i][j]表示(i,j)$向上最远的没被占领的地方,用一个递增单调栈维护每列的高h和往左最远的不小于它高度的列,加入$h$时,若$h$比栈顶小,则计算,并更新往左的最远列,否则入栈。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 using namespace std;
 6 const int N=2010;
 7 struct node
 8 {
 9     int h,x;
10 }s[N];
11 int a[N][N];
12 int n,m;
13 int ans;
14 int pre[N][N];
15 
16 int main()
17 {
18     scanf("%d%d",&n,&m);
19     for(int i=1;i<=n;i++)
20     for(int j=1;j<=m;j++)
21     {
22         char x;
23         cin>>x;
24         if(x=='F')
25         {
26             pre[i][j]=pre[i-1][j]+1;
27         }
28     }
29     for(int i=1;i<=n;i++)
30     {
31         int top=0;
32         for(int j=1;j<=m+1;j++)
33         {
34             int xx=j;
35             while(pre[i][j]<=s[top].h&&top)
36             {
37                 if(s[top].h)ans=max(ans,s[top].h*(j-s[top].x));
38                 xx=s[top].x;
39                 top--;
40             }
41             top++;
42             s[top].h=pre[i][j];s[top].x=xx;
43         }
44     }cout<<ans*3;
45 }
show you the code

 高精度

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N=20010;
 4 char tmp[N];
 5 struct bigint 
 6 {
 7     int num[N];
 8     int l;
 9 }x,y,z;
10 
11 bigint operator + (bigint a,bigint b)
12 {
13     bigint c;c.l=1;
14     int x=0;
15     while(c.l<=a.l||c.l<=b.l)
16     {
17         c.num[c.l]=a.num[c.l]+b.num[c.l]+x;//Õý³£¼Ó 
18         x=c.num[c.l]/10;c.num[c.l]%=10;//½øλ 
19         c.l++;
20     }
21     c.num[c.l]=x;//×îºóһλ½øµô£¨²»¹ÜÓÐûÓнø£© 
22     if(c.num[c.l]==0)c.l--;//È¥0 
23     return c;
24 }
25 
26 bigint operator - (bigint a,bigint b)
27 {
28     if(a.l<b.l)swap(a,b),cout<<"-";//¸ºÊý 
29     for(int i=1;i<=a.l;i++)
30     {
31         a.num[i]=a.num[i]-b.num[i];//Õý³£¼õ 
32         if(a.num[i]<0)a.num[i]+=10,a.num[i+1]--;//½èλ 
33     }
34     while(a.num[a.l]==0&&a.l>1)a.l--;//È¥0 
35     return a;
36 }
37 
38 bigint operator * (bigint a,bigint b)
39 {
40     bigint c;c.l=a.l+b.l;
41     for(int i=1;i<=a.l;i++)
42     for(int j=1;j<=b.l;j++)
43     c.num[i+j-1]+=a.num[i]*b.num[j];
44     for(int i=1;i<c.l;i++)if(c.num[i]>9)c.num[i+1]+=c.num[i]/10,c.num[i]%=10;
45     while(!c.num[c.l]&&c.l>1)c.l--;
46     return c;
47 }
48 
49 inline void print(bigint x)
50 {
51     for(int i=x.l;i>=1;i--)
52     cout<<x.num[i];
53 }
54 
55 int main()
56 {
57     //Õý¶Á×Ö·û£¬·´×ªÊý×飬´ÓµÍλ¿ªÊ¼´¦Àí 
58     cin>>tmp;x.l=strlen(tmp);for(int i=0;i<x.l;i++)x.num[x.l-i]=tmp[i]-'0';
59     cin>>tmp;y.l=strlen(tmp);for(int i=0;i<y.l;i++)y.num[y.l-i]=tmp[i]-'0';
60     //z=x+y;print(z);
61     //z=x-y;print(z);
62     z=x*y;print(z);
63 }
show you the code

 最长上升(不上升)子序列(nlogn)

d数组为满足的合法序列,用贪心的思路对于使len相等的多个元素,以最小(大)的结尾一定是最优的

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N=100010;
 4 int a[N],d1[N],d2[N],n;
 5 int len1,len2;
 6 
 7 int main()
 8 {
 9     while(cin>>a[++n]);n--;
10     d1[1]=a[1];d2[1]=a[1];
11     len1=len2=1;
12     for(int i=2;i<=n;i++)
13     {
14         if(d1[len1]>=a[i])d1[++len1]=a[i];
15         else
16         {
17             int tmp=upper_bound(d1+1,d1+1+len1,a[i],greater<int>())-d1;
18             d1[tmp]=a[i];
19         }
20         if(d2[len2]<a[i])d2[++len2]=a[i];
21         else
22         {
23             int tmp=lower_bound(d2+1,d2+1+len2,a[i])-d2;
24             d2[tmp]=a[i];
25         }
26     }
27     cout<<len1<<endl<<len2;
28 }
show you the code

最长公共子序列(nlogn)

考虑LIS为一个数列和{1,2,3...n}的LCS,那么我们也可以把LCS转化为LIS,具体做法:用$b$中的$a[i],a[j]$的相对位置来重新定义$a[i]和a[j]$的大小关系。这样我们维护m[b[i]]=i的一个映射,如果$m[a[i]]<m[a[j]]$那么我们认为$“a[i]<a[j]”$。

 1 #include<bits/stdc++.h>
 2 #define I inline
 3 using namespace std;
 4 const int N=100010;
 5 typedef long long ll;
 6 const int inf=2147483647;
 7 I int read()
 8 {
 9     int x=0,f=1;char ch=getchar();
10     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
11     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
12     return x*f;
13 }
14 
15 int n,a[N],b[N],m[N],f[N],ans;
16 
17 int main()
18 {
19     n=read();
20     for(int i=1;i<=n;i++)a[i]=read(),f[i]=inf;
21     for(int i=1;i<=n;i++)b[i]=read(),m[b[i]]=i;
22     f[1]=a[1];ans=1;
23     for(int i=2;i<=n;i++)
24     {
25         if(m[a[i]]>f[ans]){f[++ans]=m[a[i]];continue;}
26         int tmp=lower_bound(f+1,f+1+ans,m[a[i]])-f;
27         f[tmp]=m[a[i]];
28     }
29     cout<<ans;
30 }
show you the code

 字典树求异或最大值

 1 void insert(int x)
 2 {
 3     int u=1;
 4     for(int i=(1<<30);i;i>>=1)
 5     {
 6         bool c=(i&x)?1:0;
 7         if(!ch[u][c])ch[u][c]=++cnt;
 8         u=ch[u][c];
 9     }
10 }
11 
12 int query(int x)
13 {
14     int u=1,res=0;
15     for(int i=(1<<30);i;i>>=1)
16     {
17         bool c=(i&x)?0:1;
18         if(ch[u][c])res+=i,u=ch[u][c];
19         else u=ch[u][!c];
20     }return res;
21 }
show you the code
原文地址:https://www.cnblogs.com/THRANDUil/p/11782661.html