zoukankan      html  css  js  c++  java
  • Amadeus模板

    数据结构

    树链剖分(bzoj1036)

      1 #include<cstring>
      2 #include<algorithm>
      3 #include<cstdio>
      4 #include<vector>
      5 using namespace std;
      6 const int maxn=30000,inf=1e9;
      7 struct wjmzbmr
      8 {
      9     int tid,top,size,son,dep,father,v;
     10 }tree[maxn+50];
     11 struct fotile96
     12 {
     13     int maxnum,sum;
     14 }f[4*maxn+50];
     15 vector<int> g[maxn+50];
     16 int pos[maxn+50];
     17 int n,label=0,q;
     18 void dfs(int x,int fa,int dep)
     19 {
     20     tree[x]=(wjmzbmr){0,0,1,0,dep,fa,tree[x].v};
     21     int m=0;
     22     for(int i=0;i<g[x].size();++i)
     23         if(g[x][i]!=fa)
     24         {
     25             dfs(g[x][i],x,dep+1);
     26             tree[x].size+=tree[g[x][i]].size;
     27             if(tree[g[x][i]].size>m) m=tree[g[x][i]].size,tree[x].son=g[x][i];
     28         }
     29 }
     30 void connect(int x,int top)
     31 {
     32     tree[x].tid=++label,pos[tree[x].tid]=x;
     33     tree[x].top=top;
     34     if(tree[x].son!=0) connect(tree[x].son,top);
     35     for(int i=0;i<g[x].size();++i)
     36         if(g[x][i]!=tree[x].father&&g[x][i]!=tree[x].son) connect(g[x][i],g[x][i]);
     37 }
     38 void make(int k,int l,int r)
     39 {
     40     if(l>r) return;
     41     if(l==r) f[k].maxnum=f[k].sum=tree[pos[l]].v;
     42     else
     43     {
     44         int mid=(l+r)>>1;
     45         make(k*2,l,mid);
     46         make(k*2+1,mid+1,r);
     47     f[k].sum=f[k*2].sum+f[k*2+1].sum;
     48     f[k].maxnum=max(f[k*2].maxnum,f[k*2+1].maxnum);
     49     }
     50 }
     51 void change(int k,int l,int r,int x,int y)
     52 {
     53     if(l>r||r<x||l>x) return;
     54     if(l==r)
     55     {
     56         if(l==x) f[k].maxnum=y,f[k].sum=y;
     57         return;
     58     }
     59     int mid=(l+r)>>1;
     60     change(k*2,l,mid,x,y);
     61     change(k*2+1,mid+1,r,x,y);
     62     f[k].sum=f[k*2].sum+f[k*2+1].sum;
     63     f[k].maxnum=max(f[k*2].maxnum,f[k*2+1].maxnum);
     64 }
     65 int qqmax(int k,int l,int r,int ll,int rr)
     66 {
     67     if(l>r||l>rr||r<ll) return -inf;
     68     if(l>=ll&&r<=rr) return f[k].maxnum;
     69     int mid=(l+r)>>1;
     70     return max(qqmax(k*2,l,mid,ll,rr),qqmax(k*2+1,mid+1,r,ll,rr));
     71 }
     72 int qmax(int x,int y)
     73 {
     74     int ans=-inf;
     75     while(tree[x].top!=tree[y].top)
     76     {
     77         if(tree[tree[x].top].dep<tree[tree[y].top].dep) swap(x,y);
     78         ans=max(ans,qqmax(1,1,n,tree[tree[x].top].tid,tree[x].tid));
     79         x=tree[tree[x].top].father;
     80     }
     81     if(tree[x].dep>tree[y].dep) swap(x,y);
     82     ans=max(ans,qqmax(1,1,n,tree[x].tid,tree[y].tid));
     83     return ans;
     84 }
     85 int qqsum(int k,int l,int r,int ll,int rr)
     86 {
     87     if(l>r||l>rr||r<ll) return 0;
     88     if(l>=ll&&r<=rr) return f[k].sum;
     89     int mid=(l+r)>>1;
     90     return qqsum(k*2,l,mid,ll,rr)+qqsum(k*2+1,mid+1,r,ll,rr);
     91 }
     92 int qsum(int x,int y)
     93 {
     94     int ans=0;
     95     while(tree[x].top!=tree[y].top)
     96     {
     97         if(tree[tree[x].top].dep<tree[tree[y].top].dep) swap(x,y);
     98         ans+=qqsum(1,1,n,tree[tree[x].top].tid,tree[x].tid);
     99         x=tree[tree[x].top].father;
    100     }
    101     if(tree[x].dep>tree[y].dep) swap(x,y);
    102     ans+=qqsum(1,1,n,tree[x].tid,tree[y].tid);
    103     return ans;
    104 }
    105 int main()
    106 {
    107     scanf("%d",&n);
    108     for(int i=1;i<=n;++i) g[i].clear();
    109     for(int i=1;i<n;++i)
    110     {
    111         int x,y;
    112         scanf("%d %d",&x,&y);
    113         g[x].push_back(y);
    114         g[y].push_back(x);
    115     }
    116     for(int i=1;i<=n;++i) scanf("%d",&tree[i].v);
    117     dfs(1,0,0);
    118     connect(1,1);
    119     make(1,1,n);
    120     scanf("%d
    ",&q);
    121     for(int i=1;i<=q;++i)
    122     {
    123         int x,y;
    124         char s[10];
    125         scanf("%s %d %d
    ",s,&x,&y);
    126         if(s[0]=='C') change(1,1,n,tree[x].tid,y);
    127         if(s[1]=='M') printf("%d
    ",qmax(x,y));
    128         if(s[1]=='S') printf("%d
    ",qsum(x,y));
    129     }
    130     return 0;
    131 }
    View Code

    主席树求区间K小(带修改)

     1 //时间是O(nlog^2n)
     2 //空间也是O(nlog^2n),不过可以采用地址回收
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<cstdio>
     6 #include<vector>
     7 using namespace std;
     8 const int maxn=5e4;
     9 vector<int> L,R;
    10 int sorta[maxn*2+50],a[maxn*2+50],rk[maxn+50];
    11 int ch[maxn*20*20+50][2],sum[maxn*20*20+50],root[maxn+50];
    12 int sz=0,len=0;
    13 int n,m,T;
    14 int lowbit(int x)
    15 {
    16     return x&(-x);
    17 }
    18 int change(int last,int l,int r,int x,int type)//type=1表示加上x,type=-1表示减去x
    19 {
    20     int k=++len;
    21     ch[k][0]=ch[last][0],ch[k][1]=ch[last][1],sum[k]=sum[last]+type;
    22     if(l==r) return k;
    23     int mid=(l+r)>>1;
    24     if(x<=mid) ch[k][0]=change(ch[last][0],l,mid,x,type);else ch[k][1]=change(ch[last][1],mid+1,r,x,type);
    25     return k;
    26 }
    27 int query(int l,int r,int k)//询问[l,R]之间的第k小的值
    28 {
    29     if(l==r) return l;
    30     int suml=0,sumr=0;
    31     for(int i=0;i<L.size();++i) suml+=sum[ch[L[i]][0]];
    32     for(int i=0;i<R.size();++i) sumr+=sum[ch[R[i]][0]];
    33     int mid=(l+r)>>1;
    34     if(k<=sumr-suml)
    35     {
    36         for(int i=0;i<L.size();++i) L[i]=ch[L[i]][0];
    37         for(int i=0;i<R.size();++i) R[i]=ch[R[i]][0];
    38         return query(l,mid,k);
    39     }
    40     else
    41     {
    42         for(int i=0;i<L.size();++i) L[i]=ch[L[i]][1];
    43         for(int i=0;i<R.size();++i) R[i]=ch[R[i]][1];
    44         return query(mid+1,r,k-(sumr-suml));
    45     }
    46 }
    47 int main()
    48 {
    49     scanf("%d",&T);
    50     while(T--)
    51     {
    52         scanf("%d%d",&n,&m);
    53         for(int i=1;i<=n;++i) scanf("%d",&a[i]),sorta[i]=a[i];
    54         sort(sorta+1,sorta+n+1);
    55         len=0,sz=1;
    56         rk[1]=sorta[1];
    57         for(int i=2;i<=n;++i) if(sorta[i]!=sorta[i-1]) sorta[++sz]=sorta[i],rk[sz]=sorta[i];//离散
    58         memset(root,0,sizeof(root));
    59         for(int i=1;i<=n;++i)
    60         {
    61             int id=lower_bound(sorta+1,sorta+sz+1,a[i])-sorta;
    62             for(int j=i;j<=n;j+=lowbit(j))
    63                 root[j]=change(root[j],1,sz,id,1);//每个点自己建
    64         }
    65         while(m--)
    66         {
    67             char c=' ';
    68             int x,y,k;
    69             while(c!='Q'&&c!='C') c=getchar();
    70             if(c=='C')
    71             {
    72                 scanf("%d%d",&x,&y);
    73                 int id=lower_bound(sorta+1,sorta+sz+1,a[x])-sorta;
    74                 for(int i=x;i<=n;i+=lowbit(i)) root[i]=change(root[i],1,sz,id,-1);
    75                 a[x]=y;
    76                 id=lower_bound(sorta+1,sorta+sz+1,a[x])-sorta;
    77                 for(int i=x;i<=n;i+=lowbit(i)) root[i]=change(root[i],1,sz,id,1);
    78             }
    79             else
    80             {
    81                 scanf("%d%d%d",&x,&y,&k);
    82                 L.clear(),R.clear();
    83                 for(int i=x-1;i;i-=lowbit(i)) L.push_back(root[i]);
    84                 for(int i=y;i;i-=lowbit(i)) R.push_back(root[i]);
    85                 printf("%d
    ",rk[query(1,sz,k)]);
    86             }
    87         }
    88     }
    89     return 0;
    90 }
    View Code

    splay维护数列问题

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 const int maxn=2e5,inf=1e9;
      4 int pre[maxn+50],ch[maxn+50][2],flip[maxn+50],key[maxn+50],sz[maxn+50],mi[maxn+50],add[maxn+50];
      5 int a[maxn+50];
      6 int n,root=0,len=0,m;
      7 struct wjmzbmr
      8 {
      9     int num,id;
     10     bool operator < (const wjmzbmr& x) const
     11     {
     12         return num<x.num||(num==x.num&&id<x.id);
     13     }
     14 }b[maxn+50];
     15 void update(int k)
     16 {
     17     int l=ch[k][0],r=ch[k][1];
     18     sz[k]=1+sz[l]+sz[r];
     19     mi[k]=min(key[k],min(mi[l],mi[r]));
     20 }
     21 void pushdown(int k)
     22 {
     23     int& l=ch[k][0];
     24     int& r=ch[k][1];
     25     if(add[k])
     26     {
     27         if(l) add[l]+=add[k],mi[l]+=add[k],key[l]+=add[k];
     28         if(r) add[r]+=add[k],mi[r]+=add[k],key[r]+=add[k];
     29         add[k]=0;
     30     }
     31     if(flip[k])
     32     {
     33         flip[k]=0;
     34         swap(l,r);
     35         if(l) flip[l]^=1;
     36         if(r) flip[r]^=1;
     37     }
     38 }
     39 void rorate(int k,int d)
     40 {
     41     int f=pre[pre[k]],p=pre[k];
     42     pushdown(p),pushdown(k);
     43     ch[p][d^1]=ch[k][d];
     44     pre[ch[k][d]]=p;
     45     ch[k][d]=p;
     46     pre[k]=f;
     47     pre[p]=k;
     48     if(f) ch[f][ch[f][1]==p]=k;else root=k;
     49     update(p),update(k);
     50 }
     51 void splay(int x,int goal)
     52 {
     53     pushdown(x);
     54     while(pre[x]!=goal)
     55     {
     56         pushdown(x);
     57         if(pre[pre[x]]==goal) rorate(x,ch[pre[x]][0]==x);
     58         else
     59         {
     60             int d1=ch[pre[x]][0]==x,d2=ch[pre[pre[x]]][0]==pre[x];
     61             if(d1==d2) rorate(pre[x],d2),rorate(x,d1);
     62             else rorate(x,d1),rorate(x,d2);
     63         }
     64     }
     65     update(x);
     66     if(goal==0) root=x;
     67 }
     68 int build(int l,int r,int fa)
     69 {
     70     if(l>r) return 0;
     71     if(l==r)
     72     {
     73         pre[l]=fa,ch[l][0]=ch[l][1]=0,add[l]=flip[l]=0,key[l]=mi[l]=a[l],sz[l]=1;
     74         return l;
     75     }
     76     int mid=(l+r)>>1;
     77     pre[mid]=fa,ch[mid][0]=ch[mid][1]=0,add[mid]=flip[mid]=0,key[mid]=mi[mid]=a[mid],sz[mid]=1;
     78     ch[mid][0]=build(l,mid-1,mid),ch[mid][1]=build(mid+1,r,mid);
     79     update(mid);
     80     return mid;
     81 }
     82 void find(int k,int goal)
     83 {
     84     int t=root;
     85     while(true)
     86     {
     87         pushdown(t);
     88         if(sz[ch[t][0]]+1==k) break;
     89         if(k<=sz[ch[t][0]]) t=ch[t][0];else k-=sz[ch[t][0]]+1,t=ch[t][1];
     90     }
     91     splay(t,goal);
     92 }
     93 void make(int l,int r,int c)//将区间[l,r]剪掉,接在新序列的第c位后面
     94 {
     95     find(l-1,0);
     96     find(r+1,root);
     97     int u=ch[ch[root][1]][0];
     98     find(sz[ch[root][0]]+1+sz[u],ch[root][1]);
     99     u=ch[ch[root][1]][0];
    100     ch[ch[root][1]][0]=0;
    101     update(ch[root][1]),update(root);
    102     find(c,0);
    103     ch[u][1]=ch[root][1],ch[root][1]=u;
    104     pre[ch[u][1]]=u,pre[u]=root;
    105     update(u),update(root);
    106 }
    107 int main()
    108 {
    109     scanf("%d",&n);
    110     for(int i=2;i<=n+1;++i) scanf("%d",&a[i]);
    111     mi[0]=key[0]=inf;
    112     root=build(1,n+2,0);
    113     len=n+2;
    114     scanf("%d",&m);
    115     while(m--)
    116     {
    117         char s[10];
    118         int l,r,x;
    119         scanf("%s",s);
    120         if(s[0]=='A')//[l,r]加上x
    121         {
    122             scanf("%d%d%d",&l,&r,&x);
    123             ++l,++r;
    124             find(l-1,0);
    125             find(r+1,root);
    126             int u=ch[ch[root][1]][0];
    127             add[u]+=x,key[u]+=x,mi[u]+=x;
    128             update(ch[root][1]),update(root);
    129         }
    130         if(s[0]=='R'&&s[3]=='E')//[l,r]反转
    131         {
    132             scanf("%d%d",&l,&r);
    133             ++l,++r;
    134             find(l-1,0);
    135             find(r+1,root);
    136             int u=ch[ch[root][1]][0];
    137             flip[u]^=1;
    138         }
    139         if(s[0]=='R'&&s[3]=='O')//[l,r]循环右移x次
    140         {
    141             scanf("%d%d%d",&l,&r,&x);
    142             ++l,++r;
    143             x%=r-l+1;
    144             make(l,r-x,x+l-1);
    145         }
    146         if(s[0]=='I')//在l后插入一个位置,初值为x
    147         {
    148             scanf("%d%d",&l,&x);
    149             ++l;
    150             find(l,0);
    151             int u=ch[root][1];
    152             ++len;
    153             pre[len]=root,ch[len][0]=ch[len][1]=0,add[len]=flip[len]=0,key[len]=mi[len]=x,sz[len]=1;
    154             ch[root][1]=len;
    155             ch[len][1]=u;
    156             pre[u]=len;
    157             update(len),update(root);
    158         }
    159         if(s[0]=='D')//删除第i个位置
    160         {
    161             scanf("%d",&l);
    162             ++l;
    163             find(l-1,0);
    164             find(l+1,root);
    165             ch[ch[root][1]][0]=0;
    166             update(ch[root][1]),update(root);
    167         }
    168         if(s[0]=='M')//求[l,r]最小值
    169         {
    170             scanf("%d%d",&l,&r);
    171             ++l,++r;
    172             find(l-1,0);
    173             find(r+1,root);
    174             printf("%d
    ",mi[ch[ch[root][1]][0]]);
    175         }
    176     }
    177     return 0;
    178 }
    View Code

    Link-Cut Tree

      1 struct LCT
      2 {
      3     int ch[maxn+5][2],fa[maxn+5],flip[maxn+5];
      4     int top;
      5     int q[maxn+5];
      6     int mx[maxn+5];
      7     int s1[maxn+5],s3[maxn+5],sz[maxn+5];//sz 实际子树大小  s1 指向某个点的非偏爱子树的大小和 s3 splay内子树中每个点的s1的和
      8     void init()
      9     {
     10         for(int i=1;i<=n;++i) mx[i]=i,sz[i]=1,s3[i]=s1[i]=flip[i]=fa[i]=ch[i][0]=ch[i][1]=0;
     11     }
     12     bool isroot(int x)
     13     {
     14         return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;
     15     }
     16     void update(int x)
     17     {
     18         int l=ch[x][0],r=ch[x][1];
     19         mx[x]=x;
     20         if(val[mx[l]]>val[mx[x]])mx[x]=mx[l];
     21         if(val[mx[r]]>val[mx[x]])mx[x]=mx[r];
     22         sz[x]=s3[r]+s1[x]+1;
     23         s3[x]=s3[l]+s3[r]+s1[x]+1;
     24     }
     25     void pushdown(int x)
     26     {
     27         int l=ch[x][0],r=ch[x][1];
     28         if(flip[x])
     29         {
     30             flip[x]^=1;flip[l]^=1;flip[r]^=1;
     31             swap(ch[x][0],ch[x][1]);
     32             update(x);
     33         }
     34     }
     35     void rotate(int &x)
     36     {
     37         int y=fa[x],z=fa[y],l,r;
     38         if(ch[y][0]==x) l=0;
     39         else l=1;
     40         r=l^1;
     41         if(!isroot(y))
     42         {
     43             if(ch[z][0]==y) ch[z][0]=x;
     44             else ch[z][1]=x;
     45         }
     46         fa[x]=z;fa[y]=x;fa[ch[x][r]]=y;
     47         ch[y][l]=ch[x][r];ch[x][r]=y;
     48         update(y);update(x);
     49     }
     50     void splay(int &x)
     51     {
     52         top=0;
     53         q[++top]=x;
     54         for(int i=x;!isroot(i);i=fa[i]) q[++top]=fa[i];
     55         while(top) pushdown(q[top--]);
     56         while(!isroot(x))
     57         {
     58             int y=fa[x],z=fa[y];
     59             if(!isroot(y))
     60             {
     61                 if(ch[y][0]==x^ch[z][0]==y) rotate(x);
     62                 else rotate(y);
     63             }
     64             rotate(x);
     65         }
     66     }
     67     void access(int x)
     68     {
     69         for(int t=0;x;t=x,x=fa[x])
     70         {
     71             splay(x);
     72             s1[x]+=s3[ch[x][1]];
     73             ch[x][1]=t;
     74             s1[x]-=s3[t];
     75             update(x);
     76         }
     77     }
     78     void makeroot(int x)
     79     {
     80         access(x);splay(x);flip[x]^=1;
     81         pushdown(x);
     82     }
     83     bool linked(int x,int y)
     84     {
     85         //判断点x和点y是否在一个连通块中
     86         makeroot(x);access(y);splay(y);
     87         return x==y||fa[x];
     88     }
     89     void link(int x,int y)
     90     {
     91         makeroot(x);fa[x]=y;
     92         access(y),splay(y),s1[y]+=s3[x];
     93         update(y);
     94     }
     95     void cut(int x,int y)
     96     {
     97         makeroot(x);access(y);splay(y);
     98         ch[y][0]=fa[x]=0;
     99         sz[y]-=s3[x];
    100         s3[y]-=s3[x];
    101         update(y);
    102     }
    103     int findfather(int root,int x)
    104     {
    105         //返回实际树上以root为根,x的父亲
    106         makeroot(root);
    107         access(x),splay(x);
    108         pushdown(x);
    109         int fa=ch[x][0];
    110         while(true)
    111         {
    112             pushdown(fa);
    113             if(!ch[fa][1]) break;
    114             fa=ch[fa][1];
    115         }
    116         return fa;
    117 
    118     }
    119     int querymax(int x,int y)
    120     {
    121         makeroot(x);access(y);splay(y);
    122         return mx[y];
    123     }
    124 }lct;
    View Code

    Kdtree

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 const int maxn=500000,inf=1e9;
      4 int n,m,cur,ans,root;
      5 int x[maxn+50],y[maxn+50];
      6 struct P
      7 {
      8     int mn[2],mx[2],d[2],lch,rch;
      9     int& operator[](int x) {return d[x];}
     10     friend bool operator<(P x,P y) {return x[cur]<y[cur];}
     11     friend int dis(P x,P y) {return abs(x[0]-y[0])+abs(x[1]-y[1]);}
     12 }p[maxn+50];
     13 struct kdtree
     14 {
     15     P t[2*maxn+50],T;
     16     int ans;
     17     void update(int k)
     18     {
     19         int l=t[k].lch,r=t[k].rch;
     20         for (int i=0;i<2;i++)
     21         {
     22             t[k].mn[i]=t[k].mx[i]=t[k][i];
     23             if(l) t[k].mn[i]=min(t[k].mn[i],t[l].mn[i]);
     24             if(r) t[k].mn[i]=min(t[k].mn[i],t[r].mn[i]);
     25             if(l) t[k].mx[i]=max(t[k].mx[i],t[l].mx[i]);
     26             if(r) t[k].mx[i]=max(t[k].mx[i],t[r].mx[i]);
     27         }
     28     }
     29     int build(int l,int r,int now)
     30     {
     31         cur=now;
     32         int mid=(l+r)/2;
     33         nth_element(p+l,p+mid,p+r+1);
     34         t[mid]=p[mid];
     35         for(int i=0;i<2;i++) t[mid].mx[i]=t[mid].mn[i]=t[mid][i];
     36         if(l<mid) t[mid].lch=build(l,mid-1,now^1);
     37         if(r>mid) t[mid].rch=build(mid+1,r,now^1);
     38         update(mid);
     39         return mid;
     40     }
     41     void insert(int k,int now)
     42     {
     43         if(T[now]<t[k][now])
     44         {
     45             if(t[k].lch) insert(t[k].lch,now^1);
     46             else
     47             {
     48                 t[k].lch=++n;
     49                 t[n]=T;
     50                 for(int i=0;i<2;++i) t[n].mx[i]=t[n].mn[i]=t[n][i];
     51             }
     52         }
     53         else
     54         {
     55             if(t[k].rch) insert(t[k].rch,now^1);
     56             else
     57             {
     58                 t[k].rch=++n;
     59                 t[n]=T;
     60                 for(int i=0;i<2;++i) t[n].mx[i]=t[n].mn[i]=t[n][i];
     61             }
     62         }
     63         update(k);
     64     }
     65     void ins(int x,int y)
     66     {
     67         T[0]=x,T[1]=y;
     68         T.lch=T.rch=0;
     69         insert(root,0);
     70     }
     71     int getmn(P x)
     72     {
     73         int ans=0;
     74         for(int i=0;i<2;i++)
     75         {
     76             ans+=max(T[i]-x.mx[i],0);
     77             ans+=max(x.mn[i]-T[i],0);
     78         }
     79         return ans;
     80     }//估价函数,注意如果是欧几里得距离辣么估价函数要修改
     81     int getmx(P x)
     82     {
     83         int ans=0;
     84         for(int i=0;i<2;i++) ans+=max(abs(T[i]-x.mn[i]),abs(T[i]-x.mx[i]));
     85         return ans;
     86     }
     87     void querymx(int k)
     88     {
     89         ans=max(ans,dis(t[k],T));
     90         int l=t[k].lch,r=t[k].rch,dl=-inf,dr=-inf;
     91         if (l) dl=getmx(t[l]);
     92         if (r) dr=getmx(t[r]);
     93         if (dl>dr)
     94         {
     95             if (dl>ans) querymx(l);
     96             if (dr>ans) querymx(r);
     97         }
     98         else
     99         {
    100             if (dr>ans) querymx(r);
    101             if (dl>ans) querymx(l);
    102         }
    103     }
    104     void querymn(int k)
    105     {
    106         //if(dis(t[k],T)) ans=min(ans,dis(t[k],T));
    107         ans=min(ans,dis(t[k],T));
    108         int l=t[k].lch,r=t[k].rch,dl=inf,dr=inf;
    109         if(l) dl=getmn(t[l]);
    110         if(r) dr=getmn(t[r]);
    111         if (dl<dr)
    112         {
    113             if (dl<ans) querymn(l);
    114             if (dr<ans) querymn(r);
    115         }
    116         else
    117         {
    118             if (dr<ans) querymn(r);
    119             if (dl<ans) querymn(l);
    120         }
    121     }
    122     int query(int f,int x,int y)
    123     {
    124         T[0]=x,T[1]=y;
    125         T.lch=T.rch=0;
    126         if (f==0) ans=-inf,querymx(root);
    127         else
    128             ans=inf,querymn(root);
    129         return ans;
    130     }
    131 }kdtree;
    132 int main()
    133 {
    134  
    135     scanf("%d %d",&n,&m);
    136     for(int i=1;i<=n;++i)
    137     {
    138         scanf("%d%d",&x[i],&y[i]);
    139         p[i][0]=x[i],p[i][1]=y[i];
    140     }
    141     root=kdtree.build(1,n,0);
    142     for(int i=1;i<=m;++i)
    143     {
    144         int t,x,y;
    145         scanf("%d %d %d",&t,&x,&y);
    146         if(t==1) kdtree.ins(x,y);
    147         if(t==2) printf("%d
    ",kdtree.query(1,x,y));
    148     }
    149     return 0;
    150 }
    View Code

    Kdtree套替罪羊

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 const int maxn=500000,inf=1e9;
      4 int n,m,cur,ans,root;
      5 int x[maxn+50],y[maxn+50];
      6 struct P
      7 {
      8     int mn[2],mx[2],d[2],lch,rch,sz;
      9     int& operator[](int x) {return d[x];}
     10     friend bool operator<(P x,P y) {return x[cur]<y[cur];}
     11     friend int dis(P x,P y) {return abs(x[0]-y[0])+abs(x[1]-y[1]);}
     12 }p[maxn*2+50];
     13 namespace kdtree
     14 {
     15     const double alpha=0.75;
     16     P t[2*maxn+50],T;
     17     int id[maxn+5];
     18     int ans,len,tot;
     19     bool cmp(const int x,const int y)
     20     {
     21        return p[x][cur]<p[y][cur];
     22     }
     23     void update(int k)
     24     {
     25         int l=t[k].lch,r=t[k].rch;
     26         t[k].sz=t[t[k].lch].sz+t[t[k].rch].sz+1;
     27         for (int i=0;i<2;i++)
     28         {
     29             t[k].mn[i]=t[k].mx[i]=t[k][i];
     30             if(l) t[k].mn[i]=min(t[k].mn[i],t[l].mn[i]);
     31             if(r) t[k].mn[i]=min(t[k].mn[i],t[r].mn[i]);
     32             if(l) t[k].mx[i]=max(t[k].mx[i],t[l].mx[i]);
     33             if(r) t[k].mx[i]=max(t[k].mx[i],t[r].mx[i]);
     34         }
     35     }
     36     int build(int l,int r,int now)
     37     {
     38         if(l>r) return 0;
     39         cur=now;
     40         int mid=(l+r)/2;
     41         nth_element(id+l,id+mid,id+r+1,cmp);
     42         int k=id[mid];
     43         t[k]=p[k];
     44         t[k].sz=1,t[k].lch=t[k].rch=0;
     45         for(int i=0;i<2;i++) t[k].mx[i]=t[k].mn[i]=t[k][i];
     46         if(l<mid) t[k].lch=build(l,mid-1,now^1);
     47         if(r>mid) t[k].rch=build(mid+1,r,now^1);
     48         update(k);
     49         return k;
     50     }
     51     void getid(int k)
     52     {
     53         id[++tot]=k;
     54         p[k]=t[k];
     55         if(t[k].lch) getid(t[k].lch);
     56         if(t[k].rch) getid(t[k].rch);
     57     }
     58     int rebuild(int k,int now)
     59     {
     60         tot=0;
     61         getid(k);
     62         return build(1,tot,now);
     63     }
     64     int insert(int k,int now)
     65     {
     66         if(T[now]<t[k][now])
     67         {
     68             if(t[k].lch) t[k].lch=insert(t[k].lch,now^1);
     69             else
     70             {
     71                 t[k].lch=++len;
     72                 t[len]=T;
     73                 for(int i=0;i<2;++i) t[len].mx[i]=t[len].mn[i]=t[len][i];
     74             }
     75         }
     76         else
     77         {
     78             if(t[k].rch) t[k].rch=insert(t[k].rch,now^1);
     79             else
     80             {
     81                 t[k].rch=++len;
     82                 t[len]=T;
     83                 for(int i=0;i<2;++i) t[len].mx[i]=t[len].mn[i]=t[len][i];
     84             }
     85         }
     86         update(k);
     87         if(t[k].sz*alpha+3<max(t[t[k].lch].sz,t[t[k].rch].sz)) k=rebuild(k,now);
     88         return k;
     89     }
     90     void ins(int x,int y)
     91     {
     92         T[0]=x,T[1]=y;
     93         T.sz=1;
     94         T.lch=T.rch=0;
     95         if(root==0)
     96         {
     97             len=1;
     98             t[len]=T;
     99             update(len);
    100             root=len;
    101             return;
    102         }
    103         root=insert(root,0);
    104     }
    105     int getmn(P x)
    106     {
    107         int ans=0;
    108         for(int i=0;i<2;i++)
    109         {
    110             ans+=max(T[i]-x.mx[i],0);
    111             ans+=max(x.mn[i]-T[i],0);
    112         }
    113         return ans;
    114     }//估价函数,注意如果是欧几里得距离辣么估价函数要修改
    115     int getmx(P x)
    116     {
    117         int ans=0;
    118         for(int i=0;i<2;i++) ans+=max(abs(T[i]-x.mn[i]),abs(T[i]-x.mx[i]));
    119         return ans;
    120     }
    121     void querymx(int k)
    122     {
    123         ans=max(ans,dis(t[k],T));
    124         int l=t[k].lch,r=t[k].rch,dl=-inf,dr=-inf;
    125         if (l) dl=getmx(t[l]);
    126         if (r) dr=getmx(t[r]);
    127         if (dl>dr)
    128         {
    129             if (dl>ans) querymx(l);
    130             if (dr>ans) querymx(r);
    131         }
    132         else
    133         {
    134             if (dr>ans) querymx(r);
    135             if (dl>ans) querymx(l);
    136         }
    137     }
    138     void querymn(int k)
    139     {
    140         //if(dis(t[k],T)) ans=min(ans,dis(t[k],T));
    141         ans=min(ans,dis(t[k],T));
    142         int l=t[k].lch,r=t[k].rch,dl=inf,dr=inf;
    143         if(l) dl=getmn(t[l]);
    144         if(r) dr=getmn(t[r]);
    145         if (dl<dr)
    146         {
    147             if (dl<ans) querymn(l);
    148             if (dr<ans) querymn(r);
    149         }
    150         else
    151         {
    152             if (dr<ans) querymn(r);
    153             if (dl<ans) querymn(l);
    154         }
    155     }
    156     int query(int f,int x,int y)
    157     {
    158         T[0]=x,T[1]=y;
    159         T.lch=T.rch=0;
    160         if (f==0) ans=-inf,querymx(root);
    161         else
    162             ans=inf,querymn(root);
    163         return ans;
    164     }
    165 }
    166 int main()
    167 {
    168     read(n);
    169     read(m);
    170     for(int i=1;i<=n;++i)
    171     {
    172         read(x[i]);
    173         read(y[i]);
    174         p[i][0]=x[i],p[i][1]=y[i];
    175     }
    176     kdtree::len=n;
    177     for(int i=1;i<=n;++i) kdtree::id[i]=i;
    178     root=kdtree::build(1,n,0);
    179     for(int i=1;i<=m;++i)
    180     {
    181         int t,x,y;
    182         read(t);
    183         read(x);
    184         read(y);
    185         if(t==1) kdtree::ins(x,y);
    186         if(t==2) printf("%d
    ",kdtree::query(1,x,y));
    187     }
    188     return 0;
    189 }
    View Code

    左偏树

     1 //APIO2012 dispatching
     2 #include<bits/stdc++.h>
     3 using namespace std;
     4 const int maxn=1e5;
     5 vector<int> g[maxn+50];
     6 long long cost[maxn+50],lead[maxn+50],sum[maxn+50],num[maxn+50];
     7 int l[maxn+50],r[maxn+50],dist[maxn+50];
     8 int n,m,root;
     9 long long ans=0;
    10 int merge(int u,int v)//左偏树核心操作——merge:合并两个左偏树
    11 {
    12     if(!u) return v;
    13     if(!v) return u;
    14     if(cost[u]<cost[v]) swap(u,v);//此处是大根堆
    15     r[u]=merge(r[u],v);
    16     if(dist[r[u]]>dist[l[u]]) swap(l[u],r[u]);//时刻保证dist(l)>=dist(r)
    17     if(r[u]) dist[u]=dist[r[u]]+1;else dist[u]=0;//更新dist数组
    18     num[u]=num[l[u]]+num[r[u]]+1;
    19     sum[u]=sum[l[u]]+sum[r[u]]+cost[u];//维护节点信息
    20     return u;
    21 }
    22 int del(int u)
    23 {
    24     return merge(l[u],r[u]);//删除操作就是去掉根节点,merge左右儿子
    25 }
    26 int dfs(int k)
    27 {
    28     int u=k;
    29     num[u]=1,sum[u]=cost[u];
    30     while(sum[u]>m) u=del(u);
    31     for(int i=0;i<g[k].size();++i)
    32     {
    33         int v=dfs(g[k][i]);
    34         u=merge(u,v);
    35         while(sum[u]>m) u=del(u);
    36     }
    37     ans=max(ans,lead[k]*num[u]);
    38     return u;
    39 }
    40 int main()
    41 {
    42     scanf("%d%d",&n,&m);
    43     for(int i=1;i<=n;++i) g[i].clear();
    44     for(int i=1;i<=n;++i)
    45     {
    46         int x;
    47         scanf("%d%d%d",&x,&cost[i],&lead[i]);
    48         if(lead[i]==0) root=i;
    49         g[x].push_back(i);
    50     }
    51     memset(l,0,sizeof(l));
    52     memset(r,0,sizeof(r));
    53     memset(dist,0,sizeof(dist));
    54     memset(sum,0,sizeof(sum));
    55     memset(num,0,sizeof(num));
    56     dfs(1);
    57     printf("%lld",ans);
    58     return 0;
    59 }
    View Code

    虚树

     1 void buildtree()
     2 {
     3     len=0;
     4     sort(a+1,a+m+1,cmp);//关键点
     5     id.clear();//记录出现的关键点
     6     id.push_back(a[1]);
     7     s[++len]=a[1];
     8     for(int i=2;i<=m;i++)
     9     {
    10         int x=a[i],f=lca(s[len],x);
    11         while(deep[f]<deep[s[len]])
    12         {
    13             if(deep[f]>=deep[s[len-1]])
    14             {
    15                 addedge(f,s[len],abs(deep[f]-deep[s[len]]));//虚树addedge(u,v,w)
    16                 len--;
    17                 if(f!=s[len]) s[++len]=f;
    18                 break;
    19             }
    20             addedge(s[len-1],s[len],abs(deep[s[len-1]]-deep[s[len]]));
    21             len--;
    22         }
    23         if(s[len]!= x) s[++len]=x;
    24     }
    25     while(--len) addedge(s[len],s[len+1],abs(deep[s[len+1]]-deep[s[len]]));
    26 }
    View Code

    Split-Merge Treap

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 const int maxn=1e5,inf=1e9,mod=1e6;
      4 int pre[maxn+5],ch[maxn+5][2],val[maxn+5],key[maxn+5];
      5 int n,root,len;
      6 int Rand()
      7 {
      8     int ans=0;
      9     for(int i=1;i<=8;++i) ans=ans*10+rand()%10;
     10     return ans;
     11 }
     12 void split(int k,int x,int &u,int &v)
     13 {
     14     if(!k) u=v=0;
     15     else
     16     {
     17         pushdown(k);
     18         if(x<=sz[ch[k][0]]) v=k,split(ch[k][0],x,u,ch[k][0]);
     19         else u=k,split(ch[k][1],x-sz[ch[k][0]]-1,ch[k][1],v);
     20       /*  if(val[k]<=x) u=k,split(ch[k][1],x,ch[k][1],v);
     21         else v=k,split(ch[k][0],x,u,ch[k][0]); */
     22         update(k);
     23     }
     24 }
     25 int merge(int u,int v)
     26 {
     27     /*
     28     将两个子树u,v合并,其中u子树的权值都小于v子树
     29     */
     30     if(!u) return v;
     31     if(!v) return u;
     32     pushdown(u),pushdown(v);
     33     if(key[u]<key[v])
     34     {
     35         ch[u][1]=merge(ch[u][1],v);
     36         update(u);
     37         return u;
     38     }
     39     else
     40     {
     41         ch[v][0]=merge(u,ch[v][0]);
     42         update(v);
     43         return v;
     44     }
     45 }
     46 int newnode(int x)
     47 {
     48     /*
     49     新建一个权值为x的结点
     50     */
     51     ++len;
     52     val[len]=x;
     53     ch[len][0]=ch[len][1]=0;
     54     key[len]=Rand()%1000000000;
     55     return len;
     56 }
     57 void insert(int x)
     58 {
     59     /*
     60     插入一个权值为x的结点
     61     */
     62     int u,v;
     63     split(root,x,u,v);
     64     root=merge(merge(u,newnode(x)),v);
     65 }
     66 void del(int x)
     67 {
     68     /*
     69     删除一个权值为x的结点
     70     */
     71     int u,v,c,d;
     72     split(root,x,u,v);
     73     split(u,x-1,c,d);
     74     d=merge(ch[d][0],ch[d][1]);
     75     u=merge(c,d);
     76     root=merge(u,v);
     77 }
     78 int getpre(int k,int x)
     79 {
     80     /*
     81     从以k为根的子树中找到x的前驱
     82     */
     83     if(!k) return -inf;
     84     if(x==val[k]) return x;
     85     if(x<val[k]) return getpre(ch[k][0],x);
     86     return max(val[k],getpre(ch[k][1],x));
     87 }
     88 int getsuf(int k,int x)
     89 {
     90     /*
     91     从以k为根的子树中找到x的后继
     92     */
     93     if(!k) return inf;
     94     if(x==val[k]) return x;
     95     if(x>val[k]) return getsuf(ch[k][1],x);
     96     return min(val[k],getsuf(ch[k][0],x));
     97 }
     98 int main()
     99 {
    100     srand(time(0));
    101     scanf("%d",&n);
    102     root=0;
    103     len=0;
    104     insert(-inf);
    105     insert(inf);
    106     int ans=0;
    107     int a=0,b=0;
    108     for(int i=1;i<=n;++i)
    109     {
    110         int op,x;
    111         scanf("%d%d",&op,&x);
    112         if(op==0)
    113         {
    114             if(b)
    115             {
    116                 int ans1=getpre(root,x);
    117                 int ans2=getsuf(root,x);
    118                 if(ans2-x<x-ans1) ans=(ans+abs(ans2-x))%mod,del(ans2);else ans=(ans+abs(ans1-x))%mod,del(ans1);
    119                 --b;
    120             }
    121             else ++a,insert(x);
    122         }
    123         else
    124         {
    125             if(a)
    126             {
    127                 int ans1=getpre(root,x);
    128                 int ans2=getsuf(root,x);
    129                 if(ans2-x<x-ans1) ans=(ans+abs(ans2-x))%mod,del(ans2);else ans=(ans+abs(ans1-x))%mod,del(ans1);
    130                 --a;
    131             }
    132             else ++b,insert(x);
    133         }
    134     }
    135     printf("%d
    ",ans);
    136     return 0;
    137 }
    View Code

    点分治

      1 int getroot(int u)
      2 {
      3     int t=1;
      4     q[0]=u;
      5     f[u]=-1;
      6     for(int i=0;i<t;++i)
      7     {
      8         u=q[i];
      9         for(auto v:g[u])
     10             if (!vis[v]&&v!=f[u]) f[q[t++]=v]=u;
     11         mx[q[i]]=0;
     12         sz[q[i]]=1;
     13     }
     14     for (int i=t-1;i>=0;i--)
     15     {
     16         mx[q[i]]=max(mx[q[i]],t-sz[q[i]]);
     17         if(mx[q[i]]*2<=t) return q[i];
     18         sz[f[q[i]]]+=sz[q[i]];
     19         mx[f[q[i]]]=max(mx[f[q[i]]],sz[q[i]]);
     20     }
     21     return 0;
     22 }
     23 void getdeep(int k,int fa,int f)
     24 {
     25     father[k]=fa;
     26     dep[k]=dep[fa]+1;
     27     maxd[k]=dep[k];
     28     par[k]=f;
     29     L[k]=++t;
     30     p[t]=k;
     31     for(auto u:g[k])
     32     {
     33         if(u==fa||vis[u]) continue;
     34         getdeep(u,k,f);
     35         maxd[k]=max(maxd[k],maxd[u]);
     36     }
     37     R[k]=t;
     38 }
     39 void solve(int k)
     40 {
     41     t=0;
     42     maxd[k]=dep[k]=0;
     43     L[k]=++t;
     44     p[1]=k;
     45     for(auto u:g[k])
     46     {
     47         if(vis[u]) continue;
     48         getdeep(u,k,u);
     49         maxd[k]=max(maxd[k],maxd[u]);
     50     }
     51     R[k]=t;
     52 
     53     for(int i=0;i<=maxd[k];++i) s[i]=0;
     54     for(int i=1;i<=t;++i)
     55     {
     56         int u=p[i];
     57         if(u>n) continue;
     58         ++s[dep[u]];
     59         if(dep[u]==D) res[k][par[u]]++;
     60     }
     61     ss[0]=s[0];
     62     for(int i=1;i<=maxd[k];++i) ss[i]=ss[i-1]+s[i];
     63     ans[k]+=ss[min(D-1,maxd[k])];
     64     for(int i=2;i<=t;++i)
     65     {
     66         int u=p[i];
     67         if(D-1-dep[u]>=0) ans[u]+=ss[min(D-1-dep[u],maxd[k])];
     68         if(D>=dep[u]&&D-dep[u]<=maxd[k])
     69         res[u][father[u]]+=s[D-dep[u]];
     70     }
     71 
     72     for(auto u:g[k])
     73     {
     74         if(vis[u]) continue;
     75         for(int i=0;i<=maxd[u];++i) s[i]=ss[i]=0;
     76         for(int i=L[u];i<=R[u];++i)
     77         {
     78             int v=p[i];
     79             if(v>n) continue;
     80             ++s[dep[v]];
     81         }
     82         ss[0]=s[0];
     83         for(int i=1;i<=maxd[u];++i) ss[i]=ss[i-1]+s[i];
     84         for(int i=L[u];i<=R[u];++i)
     85         {
     86             int v=p[i];
     87             if(D-1-dep[v]>=0) ans[v]-=ss[min(D-1-dep[v],maxd[u])];
     88             if(D>=dep[v]&&D-dep[v]<=maxd[u])
     89             res[v][father[v]]-=s[D-dep[v]];
     90         }
     91     }
     92     vis[k]=1;
     93     for(auto u:g[k])
     94     {
     95         if(vis[u]) continue;
     96         sum=sz[u];
     97         root=getroot(u);
     98         solve(root);
     99     }
    100 }
    View Code

    莫队算法

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int maxn=40000;
     4 int pos[maxn+5],a[maxn+5];
     5 struct wjmzbmr
     6 {
     7     int l,r,k1,k2,id,ans;
     8 }q[maxn+5];
     9 int block,n,m;
    10 int color[maxn+5],cnt[200+5],ans[maxn+5];
    11 int num[maxn+5],sum[maxn+5][200+5];
    12 bool cmp(const wjmzbmr a,const wjmzbmr b)
    13 {
    14     if(a.l/block!=b.l/block) return a.l<b.l;
    15     if((a.l/block)&1) return a.r>b.r;else return a.r<b.r;
    16 }
    17 void update(int x,int type)
    18 {
    19     --color[num[x]];
    20     if(color[num[x]]==0) --cnt[num[x]/block];
    21     --sum[num[x]][x/block];
    22     num[x]+=type;
    23     ++sum[num[x]][x/block];
    24     if(color[num[x]]==0) ++cnt[num[x]/block];
    25     ++color[num[x]];
    26 }
    27 int query(int k1,int k2)
    28 {
    29     int i=0;
    30     for(i=0;i<=n/block;++i)
    31         if(cnt[i]<k1) k1-=cnt[i];
    32         else break;
    33     int turn;
    34     for(turn=block*i;turn<block*(i+1);++turn)
    35     {
    36         if(color[turn]>0) --k1;
    37         if(k1==0) break;
    38     }
    39     for(i=0;i<=200;++i)
    40         if(sum[turn][i]<k2) k2-=sum[turn][i];
    41         else break;
    42     int ans;
    43     for(ans=block*i;ans<block*(i+1);++ans)
    44     {
    45         if(num[ans]!=turn) continue;
    46         if(num[ans]>0) --k2;
    47         if(k2==0) break;
    48     }
    49     return ans;
    50 }
    51 int main()
    52 {
    53     scanf("%d",&n);
    54     for(int i=1;i<=n;++i) scanf("%d",&a[i]);
    55     scanf("%d",&m);
    56     for(int i=1;i<=m;++i) scanf("%d%d%d%d",&q[i].l,&q[i].r,&q[i].k1,&q[i].k2),q[i].id=i;
    57     block=sqrt(n);
    58     sort(q+1,q+m+1,cmp);
    59     block=200;
    60     int l=1,r=0;
    61     for(int i=1;i<=m;++i)
    62     {
    63         while(l>q[i].l) update(a[--l],1);
    64         while(r<q[i].r) update(a[++r],1);
    65         while(r>q[i].r) update(a[r--],-1);
    66         while(l<q[i].l) update(a[l++],-1);
    67         ans[q[i].id]=query(q[i].k1,q[i].k2);
    68     }
    69     for(int i=1;i<=m;++i) printf("%d
    ",ans[i]);
    70     return 0;
    71 }
    View Code

    带修改莫队

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int maxn=1e6;
     4 int block,n,m,num,s,l,r;
     5 struct Q
     6 {
     7     int l,r,t,id;
     8     bool operator < (const Q& x) const
     9     {
    10         if(l/block!=x.l/block) return l<x.l;
    11         if(r/block!=x.r/block) return r<x.r;
    12         return t<x.t;
    13     }
    14 }q[maxn+5];
    15 struct wjmzbmr
    16 {
    17     int pos,from,to,t;
    18 }c[maxn+5];
    19 int a[maxn+5],b[maxn+5],color[maxn+5],ans[maxn+5];
    20 void add(int x,int type)
    21 {
    22     if(color[x]) --s;
    23     color[x]+=type;
    24     if(color[x]) ++s;
    25 }
    26 void ins(wjmzbmr q)
    27 {
    28     if(q.pos>=l&&q.pos<=r) add(q.from,-1),add(q.to,1);
    29     a[q.pos]=q.to;
    30 }
    31 void del(wjmzbmr q)
    32 {
    33     if(q.pos>=l&&q.pos<=r) add(q.to,-1),add(q.from,1);
    34     a[q.pos]=q.from;
    35 }
    36 int main()
    37 {
    38     int T;
    39     scanf("%d%d",&n,&T);
    40     for(int i=1;i<=n;++i) scanf("%d",&b[i]),a[i]=b[i];
    41     int time=0;
    42     while(T--)
    43     {
    44         char s[3];
    45         int x,y;
    46         scanf("%s%d%d",s,&x,&y);
    47         if(s[0]=='Q') ++m,q[m]={x,y,++time,m};
    48         else c[++num]={x,0,y,++time};
    49     }
    50     for(int i=1;i<=num;++i) c[i].from=b[c[i].pos],b[c[i].pos]=c[i].to;
    51     c[num+1].t=10000000;
    52     block=(int)(ceil(pow(n,2.0/3)));
    53     sort(q+1,q+m+1);
    54     l=1,r=0;
    55     int now=0;
    56     s=0;
    57     for(int i=1;i<=m;++i)
    58     {
    59         while(r<q[i].r) add(a[++r],1);
    60         while(l>q[i].l) add(a[--l],1);
    61         while(r>q[i].r) add(a[r--],-1);
    62         while(l<q[i].l) add(a[l++],-1);
    63         while(c[now+1].t<q[i].t) ins(c[++now]);
    64         while(c[now].t>q[i].t) del(c[now--]);
    65         ans[q[i].id]=s;
    66     }
    67     for(int i=1;i<=m;++i) printf("%d
    ",ans[i]);
    68     return 0;
    69 }
    View Code

    可持久化堆优化K短路

      1 /*
      2 可持久化堆优化k短路
      3 求最短路径树:O(nlogn)
      4 求k短路:O(mlogm+klogk)
      5 空间复杂度:O(mlogm),但具体开数组要注意常数,要看执行merge操作的次数
      6 */
      7 #include<bits/stdc++.h>
      8 using namespace std;
      9 const int maxn=100000,maxm=200000,maxsize=3000000;//maxsize是堆的最大个数
     10 const long long inf=1000000000000000LL;
     11 int a[maxn+5];
     12 long long s[maxn+5];
     13 int n,k,m,len,tot;
     14 int S,T;
     15 vector<int> g1[maxn+5];
     16 int mi[maxn+5],mx[maxn+5];
     17 int head[maxn+5],nx[maxm+5];
     18 long long dis[maxn+5];
     19 int pos[maxn+5],rt[maxn+5];
     20 struct Edge
     21 {
     22     int to;
     23     long long w;
     24 }e[maxm+5];
     25 struct node
     26 {
     27     /*
     28     u是当前堆顶的节点编号
     29     key是当前堆顶对应边的权值,边的权值定义为:走这条边要多绕多少路
     30     l,r分别是堆左右儿子的地址
     31     */
     32     int u;
     33     long long key;
     34     int l,r;
     35 }H[maxsize+5];
     36 struct heapnode
     37 {
     38     /*
     39     求k短路时候用到的数据结构
     40     len表示1~倒数第二条边的边权和
     41     root表示倒数第二条边的tail的H[tail],其中堆顶就是最后一条边
     42     */
     43     long long len;
     44     int root;
     45     bool operator < (const heapnode& x) const
     46     {
     47         return len+H[root].key>x.len+H[x.root].key;
     48     }
     49 };
     50 priority_queue<heapnode> q;
     51 void addedge(int u,int v,long long w)
     52 {
     53 
     54     //printf("%d %d %lld
    ",u,v,w);
     55     e[++len]={v,w};
     56     nx[len]=head[u];
     57     head[u]=len;
     58 }
     59 void dfs(int k,int fa)
     60 {
     61     s[k]=a[k];
     62     bool flag=0;
     63     mi[k]=n+1;
     64     mx[k]=0;
     65     for(int i=0;i<g1[k].size();++i)
     66         if(g1[k][i]!=fa)
     67         {
     68             flag=1;
     69             dfs(g1[k][i],k);
     70             s[k]+=s[g1[k][i]];
     71             mi[k]=min(mi[k],mi[g1[k][i]]);
     72             mx[k]=max(mx[k],mx[g1[k][i]]);
     73         }
     74     if(!flag) mi[k]=mx[k]=++m;
     75 }
     76 int newnode(int u,long long key)
     77 {
     78     ++tot;
     79     H[tot]={u,key,0,0};
     80     return tot;
     81 }
     82 int merge(int u,int v)
     83 {
     84     /*
     85     merge两个堆u和v
     86     这里是采用随机堆,方便合并,方便持久化
     87     */
     88     if(!u) return v;
     89     if(!v) return u;
     90     if(H[v].key<H[u].key) swap(u,v);
     91     int k=++tot;
     92     H[k]=H[u];
     93     if(rand()%2) H[k].l=merge(H[k].l,v);
     94     else H[k].r=merge(H[k].r,v);
     95     return k;
     96 }
     97 void Kshort()
     98 {
     99     /*
    100     求k短路
    101     */
    102     dis[T]=0;
    103     for(int i=0;i<T;++i) dis[i]=inf;
    104     tot=0;
    105     for(int i=m-1;i>=0;--i)
    106     {
    107         /*
    108         DAG图求最短路径树
    109         */
    110         int fa=0;
    111         for(int j=head[i];j!=-1;j=nx[j])
    112             if(dis[i]>e[j].w+dis[e[j].to])
    113             {
    114                 dis[i]=e[j].w+dis[e[j].to];
    115                 pos[i]=j;
    116                 fa=e[j].to;
    117             }
    118         rt[i]=rt[fa];
    119         for(int j=head[i];j!=-1;j=nx[j])
    120             if(j!=pos[i])
    121             {
    122                 //printf("ce : %d %d
    ",i,e[j].to);
    123                 rt[i]=merge(rt[i],newnode(e[j].to,e[j].w+dis[e[j].to]-dis[i]));
    124             }
    125     }
    126     //printf("tot : %d
    ",tot);
    127     //printf("len : %d
    ",len);
    128     //printf("m : %d
    ",m);
    129     //for(int i=0;i<=T;++i) printf("%d : %lld %d
    ",i,dis[i],pos[i]);
    130     printf("%lld
    ",dis[S]+s[1]);
    131     heapnode now={0LL,rt[S]};
    132     if(now.root) q.push(now);
    133     while(--k&&!q.empty())
    134     {
    135         /*
    136         每次从优先队列队首取出最小的边集
    137         每个边集对对应一种合法的k短路走法
    138         有两种扩展方法
    139         第一种:将最后一条边换成所在堆的次小元素(相当于从堆里把堆顶删除)
    140         第二种:新加一条边,即从最后一条边继续往后走
    141         */
    142         now=q.top();
    143         q.pop();
    144         printf("%lld
    ",now.len+H[now.root].key+dis[S]+s[1]);
    145         int id=merge(H[now.root].l,H[now.root].r);
    146         //printf("%d : %d %lld
    ",id,H[id].u,H[id].key);
    147         if(id)
    148             q.push({now.len,id});
    149         now.len+=H[now.root].key;
    150         if(rt[H[now.root].u])
    151             q.push({now.len,rt[H[now.root].u]});
    152     }
    153 }
    154 int main()
    155 {
    156     srand(time(0));
    157     scanf("%d%d",&n,&k);
    158     for(int i=1;i<=n;++i) scanf("%d",&a[i]);
    159     for(int i=1;i<n;++i)
    160     {
    161         int u,v;
    162         scanf("%d%d",&u,&v);
    163         g1[u].push_back(v);
    164         g1[v].push_back(u);
    165     }
    166     dfs(1,0);
    167     for(int i=0;i<=n+1;++i) head[i]=-1;
    168     for(int i=2;i<=n;++i) addedge(mi[i]-1,mx[i],-s[i]);
    169     for(int i=0;i<m;++i) addedge(i,i+1,0);
    170     S=0,T=m;
    171     Kshort();
    172     return 0;
    173 }
    View Code

    pbds里的rbtree

     1 #include <bits/stdc++.h>
     2 #include<ext/pb_ds/assoc_container.hpp>
     3 //#include <bits/extc++.h>
     4 using namespace std;
     5 using namespace __gnu_pbds;
     6 typedef tree<int,null_type,less<int>,rb_tree_tag,tree_order_statistics_node_update> rbtree;
     7 /*
     8 tree中不能有重复元素
     9 若要能支持重复元素,可以将int改成pair<int,int>
    10 */
    11 int main()
    12 {
    13     rbtree s;
    14     s.insert(8);
    15     s.insert(3);
    16     s.insert(5);
    17     printf("%d
    ",s.order_of_key(5));//s.order_of_key(x) s里面有多少数<x
    18     printf("%d
    ",*s.find_by_order(1));//s.find_by_order(k) s里面第k+1小的数是谁
    19     return 0;
    20 }
    View Code

    笛卡尔树

     1 pair<int,int> a[maxn+5];
     2 int lson[maxn+5],rson[maxn+5],fa[maxn+5],root;
     3 int s[maxn+5];
     4 void buildtreap(pair<int,int> *a)
     5 {
     6     /*
     7     大根堆
     8     */
     9     int top=0;
    10     for(int i=0;i<=n;++i) rson[i]=lson[i]=fa[i]=0;
    11     for(int i=1;i<=n;++i)
    12     {
    13         int last=0;
    14         while(top>=1&&a[i]>a[s[top]]) last=s[top--];
    15         if(top) rson[s[top]]=i,fa[i]=s[top];
    16         lson[i]=last;
    17         if(!last) fa[last]=i;
    18         s[++top]=i;
    19     }
    20     root=s[1];
    21 }
    View Code

    图论

    匈牙利算法

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int maxn=2000;
     4 vector<int> g[maxn+5];
     5 bool v[maxn+5];
     6 int f[maxn+5];
     7 int n,m;
     8 void addedge(int u,int v)
     9 {
    10     g[u].push_back(v);
    11     g[v].push_back(u);
    12 }
    13 bool dfs(int k)
    14 {
    15     for(int i=0;i<g[k].size();++i)
    16         if(v[g[k][i]]==0)
    17         {
    18             v[g[k][i]]=1;
    19             if(f[g[k][i]]==0||dfs(f[g[k][i]]))
    20             {
    21                 f[g[k][i]]=k;
    22                 f[k]=g[k][i];
    23                 return true;
    24             }
    25         }
    26     return false;
    27 }
    28 int main()
    29 {
    30     scanf("%d %d",&n,&m);
    31     for(int i=0;i<=n+m;++i) g[i].clear();
    32     for(int i=n+1;i<=m+n;++i)
    33     {
    34         int x,y;
    35         scanf("%d %d",&x,&y);
    36         ++x,++y;
    37         addedge(i,x);
    38         addedge(i,y);
    39     }
    40     memset(f,0,sizeof(f));
    41     int ans=0;
    42     for(int i=1;i<=n+m;++i)
    43     {
    44         if(f[i]!=0) continue;
    45         memset(v,0,sizeof(v));
    46         if(dfs(i)) ++ans;
    47     }
    48     printf("%d",ans);
    49     return 0;
    50 }
    View Code

    Dinic

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int maxn=2000,inf=1e9,maxm=90000;
     4 struct Edge
     5 {
     6     int from,to,cap,flow;
     7 }edge[maxm*2+5];;
     8 vector <int> g[maxn+5];
     9 int step[maxn];//从源点到点x的距离
    10 int iter[maxn];//定点x的第几条边开始有用
    11 int n,m,S,T,len;
    12 void addedge(int from,int to,int cap)
    13 {
    14     ++len;
    15     edge[len]={from,to,cap,0};
    16     g[from].push_back(len);
    17     ++len;
    18     edge[len]={to,from,0,0};
    19     g[to].push_back(len);
    20 }
    21 void bfs(int S)
    22 {
    23     memset(step,-1,sizeof(step));
    24     step[S]=0;
    25     queue<int> q;
    26     q.push(S);
    27     while(!q.empty())
    28     {
    29         int v=q.front();
    30         q.pop();
    31         for(int i=0;i<g[v].size();++i)
    32         {
    33             Edge &e=edge[g[v][i]];
    34             if(e.cap>e.flow&&step[e.to]<0)
    35             {
    36                 step[e.to]=step[v]+1;
    37                 q.push(e.to);
    38             }
    39         }
    40     }
    41 }
    42 int dfs(int v,int t,int f)
    43 {
    44     if(v==t) return f;
    45     for(int &i=iter[v];i<g[v].size();++i)//这里是引用,i++的同时iter也++,其实相当于上个的used,不过不用判断了
    46     {
    47         Edge &e=edge[g[v][i]];
    48         if(e.cap>e.flow&&step[e.to]>step[v])
    49         {
    50             int d=dfs(e.to,t,min(e.cap-e.flow,f));
    51             if(d>0)
    52             {
    53                 e.flow+=d;
    54                 edge[g[v][i]^1].flow-=d;
    55                 return d;
    56             }
    57         }
    58     }
    59     return 0;
    60 }
    61 int maxflow(int S,int T)
    62 {
    63     int flow=0;
    64     for(;;)
    65     {
    66         bfs(S);
    67         if(step[T]<0) return flow;
    68         memset(iter,0,sizeof(iter));
    69         int f;
    70         while((f=dfs(S,T,inf))>0)
    71             flow+=f;
    72     }
    73 }
    74 int main()
    75 {
    76         scanf("%d%d",&n,&m);
    77        S=0,T=n+1;
    78         for(int i=0;i<=T;++i) g[i].clear();
    79         len=-1;
    80         for(int i=1;i<=n;++i)
    81         {
    82             int x;
    83             scanf("%d",&x);
    84             if(x==0) addedge(S,i,1);else addedge(i,T,1);
    85         }
    86         for(int i=0;i<m;++i)
    87         {
    88             int u,v;
    89             scanf("%d%d",&u,&v);
    90             addedge(u,v,1);
    91             addedge(v,u,1);
    92         }
    93         printf("%d
    ",maxflow(S,T));
    94     return 0;
    95 }
    View Code

    最大费用最大流(可行流)

     1 /*
     2 千万要注意初始化len=-1!!!!!!!!
     3 */
     4 #include<bits/stdc++.h>
     5 using namespace std;
     6 const int maxn=200,maxm=5000,inf=1e7;
     7 const double eps=1e-12;
     8 struct wjmzbmr
     9 {
    10     int from,to,cap,flow;
    11     double cost;
    12 }edge[8*maxm];
    13 vector<int> g[maxn+50];
    14 double d[maxn+50];
    15 int a[maxn+50],b[maxn+50],last[maxn+50],f[maxn+50];
    16 int n,m,t,len,S,T;
    17 bool v[maxn+50];
    18 void add(int from,int to,int cap,double cost)
    19 {
    20     edge[++len]=(wjmzbmr){from,to,cap,0,cost},g[from].push_back(len);
    21     edge[++len]=(wjmzbmr){to,from,0,0,-cost},g[to].push_back(len);
    22 }
    23 bool spfa(int S,int T,int &flow,double &cost)
    24 {
    25     for(int i=0;i<=n+1;++i) d[i]=(double)-inf,f[i]=inf;
    26     memset(v,0,sizeof(v));
    27     d[S]=0.0,v[S]=1,last[S]=0,f[S]=inf;
    28     queue<int> q;
    29     while(!q.empty()) q.pop();
    30     q.push(S);
    31     while(!q.empty())
    32     {
    33         int u=q.front();
    34         q.pop();
    35         v[u]=0;
    36         for(int i=0;i<g[u].size();++i)
    37         {
    38             wjmzbmr& e=edge[g[u][i]];
    39             if(e.cap>e.flow&&(d[e.to]+eps<d[u]+e.cost))
    40             {
    41                 d[e.to]=d[u]+e.cost;
    42                 last[e.to]=g[u][i];
    43                 f[e.to]=min(f[u],e.cap-e.flow);
    44                 if(!v[e.to])
    45                 {
    46                     q.push(e.to);
    47                     v[e.to]=1;
    48                 }
    49             }
    50         }
    51     }
    52     if(d[T]==-inf) return false;
    53     //if(d[T]*f[T]<0) return false;最大费用可行流
    54     flow+=f[T];
    55     cost+=d[T]*f[T];
    56     int u=T;
    57     while(u!=S)
    58     {
    59         edge[last[u]].flow+=f[T];
    60         edge[last[u]^1].flow-=f[T];
    61         u=edge[last[u]].from;
    62     }
    63     return true;
    64 }
    65 int main()
    66 {
    67     scanf("%d",&t);
    68     while(t--)
    69     {
    70         scanf("%d %d",&n,&m);
    71         len=-1;
    72         for(int i=0;i<=n;++i) g[i].clear();
    73         for(int i=1;i<=n;++i) scanf("%d %d",&a[i],&b[i]);
    74         for(int i=1;i<=m;++i)
    75         {
    76             int x,y,z;double p;
    77             scanf("%d %d %d %lf",&x,&y,&z,&p);
    78             p=log2(1.0-p);
    79             if(z==0) continue;
    80             else
    81             {
    82                 add(x,y,1,0);
    83                 add(x,y,z-1,p);
    84             }
    85         }
    86         S=0,T=n+1;
    87         for(int i=1;i<=n;++i)
    88         {
    89             if(a[i]-b[i]==0) continue;
    90             if(a[i]-b[i]>0) add(S,i,a[i]-b[i],0);
    91             else add(i,T,b[i]-a[i],0);
    92         }
    93         int flow=0;double cost=0.0;
    94         while(spfa(S,T,flow,cost)) ;
    95         printf("%.2f
    ",1.0-pow(2.0,cost));
    96     }
    97     return 0;
    98 }
    View Code

    最小费用最大流(Dijkstra实现)

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define mp make_pair
     4 const int maxn=2000+5,inf=1e9;
     5 pair<int,int> a[maxn+5];
     6 struct edge
     7 {
     8     int to,cap,flow,cost,rev;
     9 };
    10 vector<edge> g[maxn+5];
    11 struct heapnode
    12 {
    13     int id,v;
    14     bool operator < (const heapnode &t) const
    15     {
    16         return v>t.v;
    17     }
    18 };
    19 priority_queue<heapnode> q;
    20 int n,m,S,T,flow,cost;
    21 int h[maxn+5],dis[maxn+5],cur[maxn+5];
    22 bool ins[maxn+5];
    23 void addedge(int from,int to,int cap,int cost)
    24 {
    25     g[from].push_back({to,cap,0,cost,(int)g[to].size()});
    26     g[to].push_back({from,0,0,-cost,(int)g[from].size()-1});
    27 }
    28 bool Dijkstra()
    29 {
    30     for (int i=0;i<=T;++i)
    31     {
    32         h[i]=min(h[i]+dis[i],inf);
    33         dis[i]=i==S?0:inf;
    34     }
    35     q.push(heapnode{S,0});
    36     while (!q.empty())
    37     {
    38         heapnode x=q.top();
    39         q.pop();
    40         if(x.v>dis[x.id]) continue;
    41         for(int i=0;i<g[x.id].size();++i)
    42         {
    43             edge e=g[x.id][i];
    44             if(e.cap>e.flow&&x.v+h[x.id]+e.cost-h[e.to]<dis[e.to])
    45             {
    46                 dis[e.to]=x.v+h[x.id]+e.cost-h[e.to];
    47                 q.push(heapnode{e.to, dis[e.to]});
    48             }
    49         }
    50     }
    51     return dis[T]<inf;
    52 }
    53 int dfs(int x,int a)
    54 {
    55     if(x == T) return a;
    56     int ans = 0;
    57     ins[x] = 1;
    58     for(int &i=cur[x];i<g[x].size();++i)
    59     {
    60         edge &e=g[x][i];
    61         if(!ins[e.to]&&dis[x]+h[x]+e.cost-h[e.to]==dis[e.to]&&e.cap>e.flow)
    62         {
    63             int now=dfs(e.to,min(a,e.cap-e.flow));
    64             e.flow += now;
    65             g[e.to][e.rev].flow-=now;
    66             ans+=now;
    67             a-=now;
    68             if (!a) break;
    69         }
    70     }
    71     ins[x] = 0;
    72     return ans;
    73 }
    74 int main()
    75 {
    76     freopen("ce.in","r",stdin);
    77     scanf("%d%d",&n,&m);
    78     for(int i=1;i<=n;++i) scanf("%d%d",&a[i].first,&a[i].second); // bottle
    79     for(int i=n+1;i<=n+m;++i) scanf("%d%d",&a[i].first,&a[i].second); // people
    80     scanf("%d%d",&a[n+m+1].first,&a[n+m+1].second);
    81     S=0,T=n+m+2;
    82     for(int i=n+1;i<=n+m;++i) addedge(S,i,1,0);
    83     addedge(S,n+m+1,n-1,0);
    84     for(int i=1;i<=n;++i) addedge(i,T,1,0);
    85     for(int i=n+1;i<=n+m+1;++i)
    86         for(int j=1;j<=n;++j)
    87             addedge(i,j,1,abs(a[i].first-a[j].first)+abs(a[i].second-a[j].second));
    88     while(Dijkstra())
    89     {
    90         memset(cur,0,sizeof(cur));
    91         int now=dfs(S,inf);
    92         flow+=now;
    93         cost+=now*(dis[T]+h[T]-h[S]);
    94     }
    95     for(int i=1;i<=n;++i) cost+=abs(a[i].first-a[n+m+1].first)+abs(a[i].second-a[n+m+1].second);
    96     printf("%d",cost);
    97     return 0;
    98 }
    View Code

    KM算法

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef int ll;
     4 const int maxn=407,inf=1e9;
     5 int nl,nr,m;
     6 struct KuhnMunkres
     7 {
     8     int n;//左边1~n个点,右边1~n个点
     9     int a[maxn+5][maxn+5];
    10     int lx[maxn+5],ly[maxn+5],sla[maxn+5];//lx是左边顶标  ly是右边顶标
    11     int fl[maxn+5],fr[maxn+5];//fl[i]表示左边第i个点匹配右边哪个点 fr[i]表示右边第i个点匹配哪个点
    12     int vx[maxn+5],vy[maxn+5],pre[maxn+5];
    13     int q[maxn+5],tp;
    14     void match(int x)
    15     {
    16         while(x)
    17         {
    18             fr[x]=pre[x];
    19             int y=fl[fr[x]];
    20             fl[fr[x]]=x;
    21             x=y;
    22         }
    23     }
    24     void find(int x)
    25     {
    26         fill(vx,vx+n+1,0);
    27         fill(vy,vy+n+1,0);
    28         fill(sla,sla+n+1,inf);
    29         q[tp=1]=x;vx[x]=1;
    30         while(1)
    31         {
    32             for(int i=1;i<=tp;i++)
    33             {
    34                 int x=q[i];
    35                 for(int y=1;y<=n;y++)
    36                 {
    37                     int t=lx[x]+ly[y]-a[x][y];
    38                     if(vy[y]||t>sla[y])continue;
    39                     pre[y]=x;
    40                     if(t==0)
    41                     {
    42                         if(!fr[y]){match(y);return;}
    43                         q[++tp]=fr[y];vy[y]=1;vx[fr[y]]=1;
    44                     }
    45                     else sla[y]=t;
    46             }
    47         }
    48         int d=inf;tp=0;
    49         for(int i=1;i<=n;i++)if(!vy[i]&&d>sla[i])d=sla[i],x=i;
    50         for(int i=1;i<=n;i++)
    51         {
    52             if(vx[i])lx[i]-=d;
    53             if(vy[i])ly[i]+=d;
    54             else sla[i]-=d;
    55         }
    56         if(!fr[x]){match(x);return;}
    57         q[++tp]=fr[x];vy[x]=vx[fr[x]]=1;
    58     }
    59 }
    60     void solve()
    61     {
    62         memset(lx,0,sizeof(lx));
    63         memset(ly,0,sizeof(ly));
    64         memset(fl,0,sizeof(fl));
    65         memset(fr,0,sizeof(fr));
    66         for(int i=1;i<=n;++i) lx[i]=*max_element(a[i]+1,a[i]+n+1);
    67         for(int i=1;i<=n;++i) find(i);
    68     }
    69 }km;
    70 int main()
    71 {
    72     scanf("%d%d%d",&nl,&nr,&m);
    73     while(m--)
    74     {
    75         int u,v;
    76         scanf("%d%d",&u,&v);
    77         scanf("%d",&km.a[u][v]);
    78     }
    79     km.n=max(nl,nr);
    80     km.solve();
    81     long long ans=0;
    82     for(int i=1;i<=nl;++i)ans+=km.a[i][km.fl[i]];
    83     printf("%lld
    ",ans);
    84     for(int i=1;i<=nl;++i)
    85         if(km.a[i][km.fl[i]]==0) printf("0 ");
    86         else
    87             printf("%d ",km.fl[i]);
    88     return 0;
    89 }
    View Code

    有向图强连通分量(两次DFS)

     1 #include<cstring>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<vector>
     5 using namespace std;
     6 const int maxn=1e5,inf=1e9;
     7 vector < int > g[maxn+50],g1[maxn+50],g2[maxn+50];
     8 bool v[maxn+50];
     9 int n,m,color[maxn+50],t[maxn+50],len,c,d[maxn+50];
    10 void dfs(int k)
    11 {
    12     v[k]=1;
    13     for(int i=0;i<g[k].size();++i)
    14         if(!v[g[k][i]]) dfs(g[k][i]);
    15     ++len;
    16     t[len]=k;
    17 }
    18 void dfs1(int k)
    19 {
    20     v[k]=1;
    21     color[k]=c;
    22     for(int i=0;i<g1[k].size();++i)
    23         if(!v[g1[k][i]]) dfs1(g1[k][i]);
    24 }
    25 bool check2(int a,int b)
    26 {
    27     if(a==b) return 0;
    28     for(int i=0;i<g2[a].size();++i)
    29         if(g2[a][i]==b) return 0;
    30     return 1;
    31 }
    32 int main()
    33 {
    34 
    35     while(scanf("%d %d",&n,&m)!=EOF)
    36     {
    37         c=0;
    38         len=0;
    39         memset(d,0,sizeof(d));
    40     for(int i=0;i<=n;++i) g[i].clear(),g1[i].clear(),g2[i].clear();
    41     for(int i=1;i<=m;++i)
    42     {
    43         int x,y;
    44         scanf("%d %d",&x,&y);
    45         g[x].push_back(y);
    46         g1[y].push_back(x);
    47     }
    48     memset(v,0,sizeof(v));
    49     memset(t,0,sizeof(t));
    50     for(int i=1;i<=n;++i) if(!v[i]) dfs(i);
    51     memset(v,0,sizeof(v));
    52     for(int i=len;i>=1;--i) if(!v[t[i]]) ++c,dfs1(t[i]);
    53     for(int i=1;i<=n;++i)
    54         for(int j=0;j<g[i].size();++j)
    55             if(check2(color[i],color[g[i][j]]))
    56                 g2[color[i]].push_back(color[g[i][j]]),++d[color[i]];
    57     int s=0,x=0;
    58     for(int i=1;i<=c;++i) if(d[i]==0) ++s,x=i;
    59     if(s>1) printf("0
    ");
    60     else
    61     {
    62         int ans=0;
    63         for(int i=1;i<=n;++i)
    64             if(color[i]==x) ++ans;
    65         printf("%d
    ",ans);
    66     }
    67     }
    68     return 0;
    69 }
    70 /*bitset优化*/
    71 void dfs(int k)
    72 {
    73     if(vis[k]==0) return;
    74     vis.reset(k);
    75     bitset<maxn+5> nx=vis&g[k];
    76     int u=nx._Find_first();
    77     while(u<=n)
    78     {
    79         dfs(u);
    80         u=nx._Find_next(u);
    81     }
    82     a.push_back(k);
    83 }
    84 void dfs1(int k)
    85 {
    86     if(vis[k]==0) return;
    87     vis.reset(k);
    88     bitset<maxn+5> nx=vis&g1[k];
    89     int u=nx._Find_first();
    90     while(u<=n)
    91     {
    92         dfs1(u);
    93         u=nx._Find_next(u);
    94     }
    95 }
    View Code

    无向图点双连通分量

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int maxn=1000,maxm=1000000;
     4 vector<int> g[maxn+50],bcc[maxn+50];
     5 int dfstime[maxn+50],low[maxn+50],color[maxn+50],head[maxn+50];
     6 bool p[maxn+5][maxn+5],map[maxn+5][maxn+5],flag;
     7 int n,m,top,c,t;
     8 bool ins[maxn+50];
     9 struct wjmzbmr
    10 {
    11     int u,v;
    12 }s[maxm];
    13 void tarjan(int k,int fa)
    14 {
    15     low[k]=dfstime[k]=++t;
    16     for(int i=0;i<g[k].size();++i)
    17     {
    18         int u=g[k][i];
    19         if(u==fa) continue;
    20         if(dfstime[u])
    21             if(dfstime[u]<dfstime[k]) low[k]=min(low[k],dfstime[u]),s[++top]={k,u};
    22             else;
    23         else
    24         {
    25             s[++top]={k,u};
    26             tarjan(u,k);
    27             low[k]=min(low[k],low[u]);
    28             if(low[u]>=dfstime[k])
    29             {
    30                 ++c;
    31                 while(1)
    32                 {
    33                     wjmzbmr e=s[top--];
    34                     if(color[e.u]!=c)
    35                     {
    36                         bcc[c].push_back(e.u);
    37                         color[e.u]=c;
    38                     }
    39                     if(color[e.v]!=c)
    40                     {
    41                         bcc[c].push_back(e.v);
    42                         color[e.v]=c;
    43                     }
    44                     if(e.u==k&&e.v==u) break;
    45                 }
    46             }
    47         }
    48     }
    49 }
    50 int main()
    51 {
    52     scanf("%d %d",&n,&m);
    53     while(!(n==0&&m==0))
    54     {
    55         for(int i=0;i<=n;++i) g[i].clear(),bcc[i].clear();
    56         memset(p,0,sizeof(p));
    57         for(int i=1;i<=m;++i)
    58         {
    59             int x,y;
    60             scanf("%d %d",&x,&y);
    61             p[x][y]=p[y][x]=1;
    62         }
    63         for(int i=1;i<=n;++i)
    64             for(int j=1;j<=n;++j)
    65                 if(i!=j&&!p[i][j]) g[i].push_back(j);
    66         memset(dfstime,0,sizeof(dfstime));
    67         memset(s,0,sizeof(s));
    68         memset(color,0,sizeof(color));
    69         top=c=t=0;
    70         for(int i=1;i<=n;++i)
    71             if(!dfstime[i]) tarjan(i,-1);
    72         scanf("%d %d",&n,&m);
    73     }
    74     return 0;
    75 }
    View Code

    无向图边双连通分量

     1 #include<bitsstdc++.h>
     2 using namespace std;
     3 const int maxn=4e5;
     4 struct wjmzbmr
     5 {
     6     int x,y,pos;
     7 };
     8 wjmzbmr e[2*maxn+50];
     9 vector<int> g[maxn+50];
    10 int dfstime[maxn+50],low[maxn+50],s[maxn+50],color[maxn+50],num[maxn+50];
    11 int n,m,top,c,t,ans1=0;
    12 bool ins[maxn+50];
    13 void tarjan(int k,int fa)
    14 {
    15     low[k]=dfstime[k]=++t;
    16     s[++top]=k;
    17     ins[k]=1;
    18     for(int i=0;i<g[k].size();++i)
    19     {
    20         int u=e[g[k][i]].y;
    21         if(fa==u) continue;
    22         if(!dfstime[u])
    23         {
    24             tarjan(u,k);
    25             //if(low[u]>dfstime[k]) p[g[k][i]]=1; 判断此边是否为桥
    26             low[k]=min(low[k],low[u]);
    27         }
    28         else
    29             if(ins[u]) low[k]=min(low[k],low[u]);
    30     }
    31     if(dfstime[k]==low[k])
    32     {
    33         ++c;
    34         while(1)
    35         {
    36             int v=s[top--];
    37             ins[v]=0,color[v]=c,++num[c];
    38             if(v==k) break;
    39         }
    40     }
    41 }
    42 int main()
    43 {
    44     scanf("%d %d",&n,&m);
    45     for(int i=0;i<=n;++i) g[i].clear();
    46     for(int i=1;i<=m;++i)
    47     {
    48         int x,y;
    49         scanf("%d %d",&x,&y);
    50         g[x].push_back(2*i-1),g[y].push_back(2*i);
    51         e[2*i-1]={x,y,i},e[2*i]={y,x,i};
    52     }
    53     memset(dfstime,0,sizeof(dfstime));
    54     for(int i=1;i<=n;++i) low[i]=n+1;
    55     memset(color,0,sizeof(color));
    56     memset(num,0,sizeof(num));
    57     memset(s,0,sizeof(s));
    58     memset(ins,0,sizeof(ins));
    59     top=c=t=0;
    60     tarjan(1,-1);
    61     return 0;
    62 }
    View Code

    图的遍历(非递归)

     1 void dfs(int k,int last)
     2 {
     3    /* L[k]=++t;
     4     deep[k]=deep[last]+1;
     5     fa[k][0]=last;
     6     for(int i=0;i<g[k].size();++i)
     7         if(g[k][i]!=last) dfs(g[k][i],k);
     8     R[k]=t;*/
     9     while(!s.empty()) s.pop();
    10     memset(head,0,sizeof(head));//head[i]表示第i个点当前遍历到了第几个相邻点
    11     s.push(0);
    12     s.push(1);
    13     while(s.size()>1)
    14     {
    15         int k=s.top();
    16         s.pop();
    17         int last=s.top();
    18         s.push(k);
    19         if(!head[k])
    20         {
    21             L[k]=++t;
    22             deep[k]=deep[last]+1;
    23             fa[k][0]=last;
    24         }
    25         if(head[k]<g[k].size())
    26             if(g[k][head[k]]==last) ++head[k];
    27         if(head[k]==g[k].size())
    28         {
    29             R[k]=t;
    30             s.pop();
    31         }
    32         else
    33             s.push(g[k][head[k]++]);
    34     }
    35 }
    View Code

    字符串

    EXKMP

     1 #include<cstring>
     2 #include<algorithm>
     3 #include<cstdio>
     4 using namespace std;
     5 const int maxn=1e6;
     6 char S[maxn+50],T[maxn+50];//S是母串,T是子串
     7 int len1,len2;
     8 int next[maxn+50],extend[maxn+50];//extend[i]表示S[i..len1-1]和T的最长公共前缀的长度,next[i]表示T[i..len2-1]和T的最长公共前缀的长度
     9 void getnext()
    10 {
    11     next[0]=len2;
    12     int j=0;
    13     while(j+1<len2&&T[j]==T[j+1]) ++j;
    14     next[1]=j;
    15     int k=1;
    16     for(int i=2;i<len2;++i)
    17     {
    18         int p=k+next[k]-1,l=next[i-k];
    19         if(i+l<p+1) next[i]=l;
    20         else
    21         {
    22             j=max(p-i+1,0);
    23             while(i+j<len2&&T[i+j]==T[j]) ++j;
    24             next[i]=j;
    25             k=i;
    26         }
    27     }
    28 }
    29 void ekmp()
    30 {
    31     int j=0;
    32     while(j<len1&&j<len2&&S[j]==T[j]) ++j;
    33     extend[0]=j;
    34     int k=0;
    35     for(int i=1;i<len1;++i)
    36     {
    37         int p=k+extend[k]-1,l=next[i-k];//p表示到达的最远位置,k是对应最远位置的i
    38         if(i+l<p+1) extend[i]=l;
    39         else
    40         {
    41             j=max(p-i+1,0);
    42             while(i+j<len1&&j<len2&&S[i+j]==T[j]) ++j;
    43             extend[i]=j;
    44             k=i;
    45         }
    46     }
    47 }
    48 int main()
    49 {
    50     scanf("%s%s",S,T);
    51     len1=strlen(S),len2=strlen(T);
    52     getnext();
    53     ekmp();
    54     for(int i=0;i<len1;++i) printf("%d ",extend[i]);
    55     return 0;
    56 }
    View Code

    Manacher

     1 #include<cstring>
     2 #include<algorithm>
     3 #include<cstdio>
     4 using namespace std;
     5 const int maxn=10000;
     6 char s[maxn*2+50];
     7 int len=1,mx=0,id=0;
     8 int p[2*maxn+50];//p[i]表示以i为中心,向两边扩展的最长长度
     9 char c;
    10 int main()
    11 {
    12     s[0]='$',s[1]='#';
    13     while(scanf("%c",&c)==1) s[++len]=c,s[++len]='#';//在原字符串每个中间插上#,包括头尾,使得回文串长度为奇数,同时为了防止越界,第一个字符设为$
    14     for(int i=0;i<=len;++i)
    15     {
    16         if(mx>i) p[i]=min(p[2*id-i],mx-i);else p[i]=1;
    17         while(s[i+p[i]]==s[i-p[i]]) ++p[i];
    18         if(i+p[i]>mx)
    19         {
    20             mx=i+p[i];
    21             id=i;
    22         }
    23     }//O(n)求p数组
    24     for(int i=0;i<=len;++i) printf("%d ",p[i]);
    25     return 0;
    26 }
    View Code

    后缀数组

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int maxn=2e5;
     4 char s[maxn+50];
     5 int sa[maxn+50],rk[maxn+50],height[maxn+50],d[maxn+50][30];
     6 int t[maxn+50],t2[maxn+50],c[maxn+50];
     7 int len,k;
     8 void getsa(int m)//m表示最大字符的编码
     9 {
    10     memset(t,-1,sizeof(t));
    11     memset(t2,-1,sizeof(t2));
    12     int *x=t,*y=t2;
    13     for(int i=0;i<m;++i) c[i]=0;
    14     for(int i=0;i<len;++i) c[x[i]=s[i]]++;
    15     for(int i=1;i<m;++i) c[i]+=c[i-1];
    16     for(int i=len-1;i>=0;--i) sa[--c[x[i]]]=i;
    17     for(int k=1;k<=len;k<<=1)
    18     {
    19         int p=0;
    20         for(int i=len-k;i<len;++i) y[p++]=i;
    21         for(int i=0;i<len;++i) if(sa[i]>=k) y[p++]=sa[i]-k;
    22         for(int i=0;i<m;++i) c[i]=0;
    23         for(int i=0;i<len;++i) c[x[y[i]]]++;
    24         for(int i=0;i<m;++i) c[i]+=c[i-1];
    25         for(int i=len-1;i>=0;--i) sa[--c[x[y[i]]]]=y[i];
    26         swap(x,y);
    27         p=1,x[sa[0]]=0;
    28         for(int i=1;i<len;++i)
    29             if(y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]) x[sa[i]]=p-1;else x[sa[i]]=p++;
    30         if(p>=len) break;
    31         m=p;
    32     }
    33 }
    34 void getheight()
    35 {
    36     int k=0;
    37     for(int i=0;i<len;++i) rk[sa[i]]=i;
    38     for(int i=0;i<len;++i)
    39     {
    40         if(k) --k;
    41         if(rk[i]==0) continue;
    42         int j=sa[rk[i]-1];
    43         while(s[i+k]==s[j+k]) ++k;
    44         height[rk[i]]=k;
    45     }
    46 }
    47 void rmq_init()
    48 {
    49     for(int i=0;i<len;i++) d[i][0]=height[i];
    50     for(int j=1;(1<<j)-1<=len;j++)
    51         for(int i=0;i+(1<<j)-1<len;i++)
    52             d[i][j]=min(d[i][j-1],d[i+(1<<(j-1))][j-1]);
    53 }
    54 int lcp(int l,int r)
    55 {
    56     if(l<0||r>=len) return 0;
    57     l=rk[l],r=rk[r];
    58     if(l>r) swap(l,r);
    59     ++l;
    60     int k=0;
    61     while((1<<(k+1))<=r-l+1) k++;
    62     return min(d[l][k],d[r-(1<<k)+1][k]);
    63 }
    64 int main()
    65 {
    66     scanf("%s",s);
    67     len=strlen(s);
    68     getsa('z'+1);
    69     getheight();
    70     rmq_init();
    71     int ans=0;
    72     for(int l=1;l<=len;++l)
    73         for(int i=0;i<len;i+=l)
    74         {
    75             int m=lcp(i,i+l);
    76             ans=max(ans,m/l+1);
    77             ans=max(ans,lcp(i-l+m%l,i+m%l)/l+1);
    78         }
    79     printf("%d
    ",ans);
    80    // for(int i=0;i<n;++i) printf("%d ",sa[i]);printf("
    ");
    81    // for(int i=0;i<n;++i) printf("%d ",rk[i]);printf("
    ");
    82    // for(int i=0;i<n;++i) printf("%d ",height[i]);printf("
    ");
    83     return 0;
    84 
    85 }
    View Code

    AC自动机

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int maxn=1e5;
     4 int ch[maxn+50][26];
     5 int sz=0,n,root=0;
     6 char s[maxn+50],S[maxn+50];
     7 int danger[maxn+50];
     8 int nx[maxn+50];
     9 int last[maxn+50];
    10 queue<int> q;
    11 bool vis[maxn+50];
    12 void buildtrie(char *s)
    13 {
    14     int u=root;
    15     int len=strlen(s);
    16     for(int i=0;i<len;++i)
    17     {
    18         int id=s[i]-'a';
    19         if(!ch[u][id]) ch[u][id]=++sz;
    20         u=ch[u][id];
    21     }
    22     ++danger[u];
    23 }
    24 void buildfail()
    25 {
    26     while(!q.empty()) q.pop();
    27     for(int i=0;i<26;++i) if(ch[root][i]) q.push(ch[root][i]),nx[ch[root][i]]=root,last[ch[root][i]]=0;
    28     while(!q.empty())
    29     {
    30         int u=q.front();
    31         q.pop();
    32         for(int i=0;i<26;++i)
    33             if(ch[u][i])
    34             {
    35                 int k=nx[u];
    36                 while(!ch[k][i]&&k) k=nx[k];
    37                 nx[ch[u][i]]=ch[k][i];
    38                 //danger[ch[u][i]]|=danger[ch[k][i]];
    39                 if(danger[ch[k][i]]) last[ch[u][i]]=ch[k][i];else last[ch[u][i]]=last[ch[k][i]];
    40                 q.push(ch[u][i]);
    41             }
    42             else ch[u][i]=u==0?0:ch[nx[u]][i];
    43     }
    44 }
    45 bool query(char *s)
    46 {
    47     int len=strlen(s);
    48     int u=root;
    49     int ans=0;
    50     for(int i=0;i<len;++i)
    51     {
    52         int id=s[i]-'a';
    53         u=ch[u][id];
    54         int v=u;
    55         while(v)
    56         {
    57             if(vis[v]) break;
    58             vis[v]=1;
    59             if(danger[v]) ans+=danger[v],danger[v]=0;
    60             v=last[v];
    61         }
    62     }
    63     return ans==n;
    64 }
    65 void init()
    66 {
    67     for(int i=0;i<=sz;++i) memset(ch[i],0,sizeof(ch[i]));
    68     for(int i=0;i<=sz;++i) danger[i]=0;
    69     for(int i=0;i<=sz;++i) last[i]=0;
    70     for(int i=0;i<=sz;++i) nx[i]=0;
    71     for(int i=0;i<=sz;++i) vis[i]=0;
    72     sz=0;
    73 }
    74 int main()
    75 {
    76     int T;
    77     scanf("%d",&T);
    78     while(T--)
    79     {
    80         scanf("%d",&n);
    81         init();
    82         int mx=0;
    83         for(int i=1;i<=n;++i)
    84         {
    85             scanf("%s",s);
    86             int l=strlen(s);
    87             if(l>mx)
    88             {
    89                 mx=l;
    90                 strcpy(S,s);
    91             }
    92             buildtrie(s);
    93         }
    94         buildfail();
    95         if(query(S)) printf("%s
    ",S);else printf("No
    ");
    96     }
    97     return 0;
    98 }
    View Code

    SAM(后缀自动机)

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 const int maxn=1e6;
      4 char s[maxn+5];
      5 int sz=0,len,last=0;
      6 int maxlen[2*maxn+50],minlen[2*maxn+50],trans[2*maxn+50][26],slink[2*maxn+50],endpos[2*maxn+50];
      7 int sa[maxn*2+5],cnt[maxn*2+5];
      8 long long ans[maxn*2+50];
      9 int suf[maxn*2+5];
     10 int g[maxn*2+5][26];
     11 bool vis[maxn*2+5];
     12 int build(int _maxlen,int _minlen,int* _trans,int _slink)
     13 {
     14     maxlen[++sz]=_maxlen;
     15     minlen[sz]=_minlen;
     16     for(int i=0;i<26;++i)
     17         if(_trans==NULL) trans[sz][i]=-1;else trans[sz][i]=_trans[i];
     18     slink[sz]=_slink;
     19     return sz;
     20 }
     21 int add(char ch,int u)
     22 {
     23     int c=ch-'a';
     24     if(trans[u][c]!=-1&&maxlen[u]+1==maxlen[trans[u][c]]) return trans[u][c]; //顺着Trie树走
     25     int z=build(maxlen[u]+1,-1,NULL,-1);
     26     int v=u;
     27     while(v!=-1&&trans[v][c]==-1) trans[v][c]=z,v=slink[v];
     28     if(v==-1)//最简单的情况,suffix-path(u->S)上都没有对应字符ch的转移
     29     {
     30         minlen[z]=1;
     31         slink[z]=0;
     32         return z;
     33     }
     34     int x=trans[v][c];
     35     if(maxlen[v]+1==maxlen[x])//较简单的情况,不用拆分x
     36     {
     37         minlen[z]=maxlen[x]+1;
     38         slink[z]=x;
     39         return z;
     40     }
     41     int y=build(maxlen[v]+1,-1,trans[x],slink[x]); //最复杂的情况,拆分x,y表示<=maxlen[v]+1的那段
     42     slink[y]=slink[x];
     43     minlen[x]=maxlen[y]+1;
     44     slink[x]=y;
     45     minlen[z]=maxlen[y]+1;
     46     slink[z]=y;
     47     int w=v;
     48     while(w!=-1&&trans[w][c]==x) trans[w][c]=y,w=slink[w];
     49     minlen[y]=maxlen[slink[y]]+1;
     50     return z;
     51 }
     52 void addedge(int u,int v,int w)
     53 {
     54     g[u][w]=v;
     55 }
     56 void goup(int k,int start,int step)
     57 {
     58     if(k==0||vis[k]) return;
     59     vis[k]=1;
     60     int father=slink[k];
     61     step-=maxlen[k]-minlen[k]+1;
     62     addedge(father,k,s[start+step]-'a');
     63     goup(father,start,step);
     64 }
     65 int main()
     66 {
     67     int T;
     68     scanf("%d",&T);
     69     while(T--)
     70     {
     71     scanf("%s",s);
     72     len=strlen(s);
     73     for(int i=0;i<=2*len;++i)
     74         {
     75             for(int j=0;j<26;++j) trans[i][j]=-1;
     76             slink[i]=-1;
     77             maxlen[i]=minlen[i]=0;
     78             memset(g[i],0,sizeof(g[i]));
     79             suf[i]=-1;
     80         }
     81     for(int i=0;i<26;++i) trans[0][i]=slink[0]=-1;
     82     maxlen[0]=minlen[0]=0;
     83     sz=0;
     84     last=0;
     85     memset(endpos,0,sizeof(endpos));
     86     for(int i=0;i<len;++i)
     87     {
     88         last=add(s[i],last);//后缀树要倒过来建
     89         suf[last]=i;
     90         endpos[last]=1;
     91     }
     92     for(int i=1;i<=sz;++i) ++cnt[maxlen[i]];
     93     for(int i=2;i<=sz;++i) cnt[i]+=cnt[i-1];
     94     for(int i=1;i<=sz;++i) sa[cnt[maxlen[i]]--]=i;
     95     for(int i=sz;i>=1;--i)
     96     {
     97         int u=sa[i];
     98         endpos[slink[u]]+=endpos[u];
     99     }
    100 
    101     for(int i=0;i<=sz;++i) vis[i]=0;
    102         for(int i=1;i<=sz;++i)
    103             if(suf[i]!=-1) goup(i,suf[i],len-suf[i]);
    104 
    105 
    106     memset(ans,0,sizeof(ans));
    107     for(int i=1;i<=sz;++i) ans[maxlen[i]]=max(ans[maxlen[i]],(long long)endpos[i]);
    108     for(int i=len-1;i>=1;--i) ans[i]=max(ans[i],ans[i+1]);
    109     for(int i=1;i<=len;++i) printf("%lld
    ",ans[i]);
    110     }
    111     return 0;
    112 }
    View Code

    回文树

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const ll mod=1e9+7;
     5 const int maxn=2000000;
     6 ll ans;
     7 ll pw[maxn+5];
     8 char s[maxn+5];
     9 struct Palindromic_Tree
    10 {
    11     int ch[maxn+5][11];//next指针,next指针和字典树类似,指向的串为当前串两端加上同一个字符构成
    12     int fail[maxn+5];//fail指针,失配后跳转到fail指针指向的节点
    13     int cnt[maxn+5];//某个点表示的回文子串出现的次数
    14     int num[maxn+5];//表示以节点i表示的最长回文串的最右端点为回文串结尾的回文串个数
    15     int len[maxn+5];//len[i]表示节点i表示的回文串的长度
    16     int last;//指向上一个字符所在的节点,方便下一次add
    17     int n;//字符数组指针
    18     int p;//节点指针
    19     int newnode(int l)
    20     {   //新建节点
    21         for(int i=0;i<=10;++i) ch[p][i]=0;
    22         cnt[p]=0;
    23         num[p]=0;
    24         len[p]=l;
    25         return p++;
    26     }
    27     void init()
    28     {   //初始化
    29         p=0;
    30         newnode(0);
    31         newnode(-1);
    32         last=0;
    33         n=0;
    34         s[n]=-1;//开头放一个字符集中没有的字符,减少特判
    35         fail[0]=1;
    36     }
    37     int get_fail(int x)
    38     {   //和KMP一样,失配后找一个尽量最长的
    39         while(s[n-len[x]-1]!=s[n]) x=fail[x];
    40         return x;
    41     }
    42     void add(int c)
    43     {
    44         c-='0';
    45         s[++n]=c;
    46         int cur=get_fail(last);//通过上一个回文串找这个回文串的匹配位置
    47         if(!ch[cur][c])
    48         {   //如果这个回文串没有出现过,说明出现了一个新的本质不同的回文串
    49             int now=newnode(len[cur]+2);//新建节点
    50             fail[now]=ch[get_fail(fail[cur])][c];//和AC自动机一样建立fail指针,以便失配后跳转
    51             ch[cur][c]=now;
    52             num[now]=num[fail[now]]+1;
    53         }
    54         last=ch[cur][c];
    55         cnt[last]++;
    56     }
    57     void count ()
    58     {
    59         for ( int i = p - 1 ; i >= 0 ; -- i ) cnt[fail[i]] += cnt[i] ;
    60         //父亲累加儿子的cnt,因为如果fail[v]=u,则u一定是v的子回文串!
    61     }
    62     void dfs(int k,ll num,int len)
    63     {
    64         for(int i=0;i<=10;++i)
    65             if(ch[k][i])
    66             {
    67                 ans=(ans+(num*10%mod+i+i*pw[len+1]%mod)%mod)%mod;
    68                 dfs(ch[k][i],(num*10%mod+i+i*pw[len+1]%mod)%mod,len+2);
    69             }
    70     }
    71     void work()
    72     {
    73         dfs(0,0LL,0);
    74         for(int i=0;i<=10;++i)
    75             if(ch[1][i])
    76             {
    77                 ans+=i;
    78                 dfs(ch[1][i],1LL*i,1);
    79             }
    80     }
    81 }PT;
    82 int main()
    83 {
    84 
    85     pw[0]=1;
    86     for(int i=1;i<=maxn;++i) pw[i]=pw[i-1]*10%mod;
    87     scanf("%s",s+1);
    88     int len=strlen(s+1);
    89     PT.init();
    90     for(int i=1;i<=len;++i) PT.add(s[i]);
    91     PT.work();
    92     printf("%lld
    ",ans);
    93     return 0;
    94 }
    View Code

    数论

    莫比乌斯反演(筛积性函数+数论分块)

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int maxn=1e5;
     4 int mu[maxn+50],prime[maxn+50],sum[maxn+50];
     5 bool f[maxn+50];
     6 int a,b,c,d,k;
     7 long long solve(int n,int m)
     8 {
     9     if(n>m) swap(n,m);
    10     long long ans=0;
    11     for(int i=1,la=0;i<=n;i=la+1)
    12     {
    13         la=min(n/(n/i),m/(m/i));
    14         ans+=(long long)(sum[la]-sum[i-1])*(n/i)*(m/i);
    15     }//对于n/i * m/i 采用分块求和的根号n+根号m的做法
    16     return ans;
    17 }
    18 int main()
    19 {
    20     mu[1]=1;
    21     memset(f,0,sizeof(f));
    22     f[1]=1;
    23     for(int i=2;i<=maxn;++i)
    24     {
    25         if(!f[i])
    26         {
    27             prime[++prime[0]]=i;
    28             mu[i]=-1;
    29         }
    30         for(int j=1;j<=prime[0];++j)
    31         {
    32             if(i*prime[j]>maxn) break;
    33             f[i*prime[j]]=1;
    34             if(i%prime[j]==0)
    35             {
    36                 mu[i*prime[j]]=0;
    37                 break;
    38             }
    39             else mu[i*prime[j]]=-mu[i];
    40         }
    41     }//筛积性函数
    42     memset(sum,0,sizeof(sum));
    43     sum[1]=mu[1];
    44     for(int i=2;i<=maxn;++i) sum[i]=sum[i-1]+mu[i];
    45     int T;
    46     scanf("%d",&T);
    47     for(int cas=1;cas<=T;++cas)
    48     {
    49         printf("Case %d: ",cas);
    50         scanf("%d%d%d%d%d",&a,&b,&c,&d,&k);
    51         if(k==0) printf("0
    ");else
    52         {
    53             long long ans=solve(b/k,d/k)-solve((a-1)/k,d/k)-solve(b/k,(c-1)/k)+solve((a-1)/k,(c-1)/k);
    54             a=max(a,c),b=min(b,d);
    55             long long ans1=solve(b/k,b/k)-solve((a-1)/k,b/k)-solve(b/k,(a-1)/k)+solve((a-1)/k,(a-1)/k);
    56             printf("%lld
    ",ans-ans1/2);
    57         }
    58     }
    59     return 0;
    60 }
    View Code

    CRT

     1 void gcd(ll a,ll b,ll &d,ll &x,ll &y)
     2 {
     3     if(!b)
     4     {
     5         d=a,x=1,y=0;
     6         return;
     7     }
     8     gcd(b,a%b,d,y,x);
     9     y-=x*(a/b);
    10 }
    11 ll inv(ll a,ll n)
    12 {
    13     ll d,x,y;
    14     gcd(a,n,d,x,y);
    15     return d==1?(x+n)%n:-1;
    16 }
    17 ll CRT(int n,ll *a,ll *m)
    18 {
    19     /*n个方程 x=a[i] (mod m[i])   (0<=i<n)*/
    20     ll M=1,d,y,x=0;
    21     for(int i=0;i<n;++i) M*=m[i];
    22     for(int i=0;i<n;++i)
    23     {
    24         ll w=M/m[i];
    25         gcd(m[i],w,d,d,y);
    26         x=(x+y*w*a[i])%M;
    27     }
    28     return (x+M)%M;
    29 }
    View Code

    类欧几里得

     1 typedef long long ll;
     2 ll solve(ll a,ll b,ll c,ll n)
     3 {
     4     /*
     5     计算 sum_{i=0..n} (ax+b)/c 的值
     6     */
     7     if(n<0) return 0;
     8     if(c<0) a=-a,b=-b,c=-c;
     9     if(a<0) b+=a*n,a=-a;
    10     if(b<0)
    11     {
    12         ll p=(-b)/c+1;
    13         //(a*x+b+p*c)/c-p
    14         return (solve(a,b+p*c,c,n)-p*(n+1))%mod;
    15     }
    16     if(a==0)
    17         return (b/c)*(n+1)%mod;
    18     if(a>=c)
    19         return (n*(n+1)/2%mod*(a/c)%mod+solve(a%c,b,c,n))%mod;
    20     if(b>=c)
    21         return ((b/c)*(n+1)%mod+solve(a,b%c,c,n))%mod;
    22     //LL m=(a*n+b)/c%MOD;
    23     ll m=(n/c*a+(n%c*a+b)/c);
    24     return ((m%mod)*(n%mod)%mod-solve(c,c-b-1,a,m-1)+mod)%mod;
    25 }
    26 ll cal(ll a,ll b,ll c,ll n)
    27 {
    28 /*
    29 计算y=(ax+b)/c下方整点个数,x=0..n
    30 要求a>=0,c>0
    31 */
    32     if(b>=0) return (solve(a,b,c,n)+n%mod+1)%mod;
    33     ll x=(-b)/a;
    34     if(x*a+b<0) ++x;
    35     if(n<x) return 0;
    36     b+=a*x;
    37     return (solve(a,b,c,n-x)+(n-x)%mod+1)%mod;
    38 }
    View Code

    杜教筛

      1 #include<bits/stdc++.h>
      2 #define debug cout<<"debug "<<++debug_num<<" :"
      3 #define pb push_back
      4 #define mp make_pair
      5 #define lson l,m,rt<<1
      6 #define rson m+1,r,rt<<1|1
      7 #define bit(a,b) ((a>>b)&1) //from 0
      8 #define all(x) (x).begin(),(x).end()
      9 using namespace std;
     10 typedef long long ll;
     11 typedef pair<int,int> PII;
     12 int debug_num=0;
     13 
     14 const int maxn=5e6+10;
     15 bool valid[maxn];
     16 ll phi[maxn];
     17 int mu[maxn];
     18 int ans[maxn/10];
     19 int tot;
     20 int up;
     21 int m;
     22 const int maxm=(1LL<<32)/maxn;
     23 ll help1[maxm];
     24 int help2[maxm];
     25 bool vis[maxm];
     26 
     27 void get_prime(int n)
     28 {
     29     memset(valid,true,sizeof(valid));
     30     tot=0;
     31     phi[1]=mu[1]=1;
     32     for(int i=2;i<=n;++i){
     33         if(valid[i]){
     34             ans[++tot]=i;
     35             mu[i]=-1;
     36             phi[i]=i-1;
     37         }
     38         for(int j=1;j<=tot && i*ans[j]<=n;++j){
     39             int tp=i*ans[j];
     40             valid[tp]=false;
     41             if(i%ans[j]==0){
     42                 mu[tp]=0;
     43                 phi[tp]=phi[i]*ans[j];
     44                 break;
     45             }
     46             else{
     47                 mu[tp]=-mu[i];
     48                 phi[tp]=phi[i]*(ans[j]-1);
     49             }
     50         }
     51     }
     52     for(int i=1;i<=n;++i){
     53         phi[i]=phi[i-1]+phi[i];
     54         mu[i]+=mu[i-1];
     55     }
     56 }
     57 
     58 ll get_phi(ll n)
     59 {
     60     return (n<=up)? phi[n] : help1[m/n];
     61 }
     62 
     63 ll get_mu(ll n)
     64 {
     65     return (n<=up)? mu[n] : help2[m/n];
     66 }
     67 
     68 void solve(ll n)
     69 {
     70     int t=m/n;
     71     if(n<=up || vis[t]) return ;
     72     vis[t]=true;
     73     help1[t]=n*(n+1)/2;//单位函数前缀和
     74     help2[t]=1;//恒等函数前缀和
     75     for(ll l=2,r;l<=n;l=r+1){
     76         r=n/(n/l);
     77         solve(n/r);
     78         help1[t]=help1[t]-(r-l+1)*get_phi(n/r);
     79         help2[t]=help2[t]-(r-l+1)*get_mu(n/r);
     80     }
     81 }
     82 
     83 int main()
     84 {
     85     //freopen("in.txt","r",stdin);
     86     up=maxn-10;
     87     get_prime(up);
     88     //cout<<clock()<<endl;
     89     //cout<<tot<<endl;
     90     //cout<<phi[up]<<endl;
     91     //for(int i=1;i<=up;++i) if(mu[i]==0) cout<<"fuck"<<endl;
     92     int t,n;
     93     cin>>t;
     94     while(t--)
     95     {
     96         cin>>n;
     97         m=n;
     98         if(n<=up) cout<<phi[n]<<" "<<mu[n]<<endl;
     99         else{
    100             memset(vis,0,sizeof(vis));//注意清空
    101             solve(n);
    102             cout<<help1[1]<<" "<<help2[1]<<endl;
    103         }
    104     }
    105     return 0;
    106 }
    View Code

    O(1)快速乘

    1 inline ll multi(ll x,ll y,ll mod)
    2 {
    3      ll tmp=(x*y-(ll)((long double)x/mod*y+1.0e-8)*mod);
    4      return tmp<0 ? tmp+mod : tmp;
    5 }
    View Code

     min25筛

      1 //f(1)=1
      2 //f(p)=p^2-p
      3 //f(p^e)=(p-1)p^(2e-1)
      4 #include<bits/stdc++.h>
      5 using namespace std;
      6 typedef long long ll;
      7 const ll mod=1e9+7,inv6=166666668;
      8 ll n,M;
      9 //pre[d][i]预处理的是2~i中的p^d的和 p是素数
     10 //suf[d][i]预处理2~n/i的p^d的和 p是素数
     11 //pre[0][i]预处理的是2~i中p^2-p的和 p是素数
     12 //suf[0][i]预处理的是2~n/i中p^2-p的和 p是素数
     13 vector<ll> pre[3],suf[3],prime;
     14 //res是n/枚举的数
     15 ll mul(ll a,ll b)
     16 {
     17     return a*b%mod;
     18 }
     19 ll add(ll a,ll b)
     20 {
     21     return (a+b)%mod;
     22 }
     23 ll sub(ll a,ll b)
     24 {
     25     return (a-b)%mod;
     26 }
     27 ll dfs(ll res,int last,ll f)
     28 {
     29     ll t=(res>M?suf[0][n/res]:pre[0][res])-pre[0][prime[last]-1];
     30     t%=mod;
     31     ll ans=mul(t,f);//需要修改
     32     for(int i=last;i<(int)prime.size();++i)
     33     {
     34         int p=prime[i];
     35         if(1LL*p*p>res) break;
     36         for(ll q=p,nres=res,nf=f*p%mod*(p-1)%mod;q*p<=res;q*=p)//nf需要修改
     37         {
     38             ans=add(ans,dfs(nres/=p,i+1,nf));   //枚举更大的数
     39             nf=mul(nf,mul(p,p));    //需要修改,继续枚举当前素数,指数大于1的时候,指数每+1,nf*=p^2
     40             ans=add(ans,nf);        //指数大于1的时候记上贡献
     41         }
     42     }
     43     return ans;
     44 }
     45 ll f(ll x)
     46 {
     47     return x*(1+x)/2%mod;
     48 }
     49 ll ff(ll x)
     50 {
     51     return x*(x+1)%mod*(2*x+1)%mod*inv6%mod;
     52 }
     53 ll solve(ll n)
     54 {
     55     M=sqrt(n);
     56     for(int i=0;i<3;++i) pre[i].clear(),pre[i].resize(M+1);
     57     for(int i=0;i<3;++i) suf[i].clear(),suf[i].resize(M+1);
     58     prime.clear();
     59     for(int i=1;i<=M;++i)
     60     {
     61         pre[1][i]=f(i)-1;
     62         suf[1][i]=f(n/i)-1;
     63         pre[2][i]=ff(i)-1;
     64         suf[2][i]=ff(n/i)-1;
     65     }
     66     for(int p=2;p<=M;++p)
     67     {
     68         if(pre[1][p]==pre[1][p-1]) continue;
     69         prime.push_back(p);
     70         const ll q=1LL*p*p,m=n/p,pnt[3]={0,pre[1][p-1],pre[2][p-1]};
     71         const int mid=M/p;
     72         const int End=min((ll)M,n/q);
     73         for(int i=1;i<=mid;++i)
     74         {
     75             suf[1][i]=sub(suf[1][i],(suf[1][i*p]-pnt[1])*p%mod);
     76             suf[2][i]=sub(suf[2][i],(suf[2][i*p]-pnt[2])*p%mod*p%mod);
     77         }
     78         for(int i=mid+1;i<=End;++i)
     79         {
     80             suf[1][i]=sub(suf[1][i],(pre[1][m/i]-pnt[1])*p%mod);
     81             suf[2][i]=sub(suf[2][i],(pre[2][m/i]-pnt[2])*p%mod*p%mod);
     82         }
     83         for(int i=M;i>=q;--i)
     84         {
     85             pre[1][i]=sub(pre[1][i],(pre[1][i/p]-pnt[1])*p%mod);
     86             pre[2][i]=sub(pre[2][i],(pre[2][i/p]-pnt[2])*p%mod*p%mod);
     87         }
     88     }
     89     for(int i=1;i<=M;++i)
     90     {
     91         pre[0][i]=(pre[2][i]-pre[1][i])%mod;
     92         suf[0][i]=(suf[2][i]-suf[1][i])%mod;
     93     }
     94     prime.push_back(M+1);
     95     return n>1?1+dfs(n,0,1):1;
     96 }
     97 int main()
     98 {
     99     scanf("%lld",&n);
    100     printf("1
    %lld
    ",(solve(n)+mod)%mod);
    101     return 0;
    102 }
    View Code

     矩阵类

     1 struct matrix
     2 {
     3     int n,a[N][N];
     4     matrix operator *(const matrix&b) const
     5     {
     6         matrix c;c.n=n;memset(c.a,0,sizeof(c.a));
     7         for (int i=0;i<n;i++)
     8             for (int j=0;j<b.n;j++)
     9                 for (int k=0;k<b.n;k++)
    10                 c.a[i][j]=(c.a[i][j]+1ll*a[i][k]*b.a[k][j])%P;
    11         return c;
    12     }
    13 }
    View Code

    多项式

    FFT

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int maxn=400000;
     4 const double pi=acos(-1.0);
     5 int l,m,n,num;
     6 int a[maxn+50],b[maxn+50];
     7 struct wjmzbmr
     8 {
     9     double r,i;
    10     wjmzbmr(double real=0.0,double image=0.0){r=real;i=image;}
    11     wjmzbmr operator + (const wjmzbmr o)
    12     {
    13         return wjmzbmr(r+o.r,i+o.i);
    14     }
    15     wjmzbmr operator - (const wjmzbmr o)
    16     {
    17         return wjmzbmr(r-o.r,i-o.i);
    18     }
    19     wjmzbmr operator * (const wjmzbmr o)
    20     {
    21         return wjmzbmr(r*o.r-i*o.i,r*o.i+i*o.r);
    22     }
    23 };
    24 wjmzbmr x1[maxn+50],x2[maxn+50];
    25 void brc(wjmzbmr *y,int l)
    26 {
    27     for(int i=1,j=l/2;i<l-1;i++)
    28     {
    29         if(i<j) swap(y[i],y[j]);
    30         int k=l/2;
    31         while(j>=k)j-=k,k/=2;
    32         if(j<k) j+=k;
    33     }
    34 }
    35 void fft(wjmzbmr *y,int l,double on)
    36 {
    37     wjmzbmr u,t;
    38     brc(y,l);
    39     for(int h=2;h<=l;h<<=1)
    40     {
    41         wjmzbmr wn(cos(on*2*pi/h),sin(on*2*pi/h));
    42         for(int j=0;j<l;j+=h)
    43         {
    44             wjmzbmr w(1,0);
    45             for(int k=j;k<j+h/2;k++)
    46             {
    47                 u=y[k];
    48                 t=w*y[k+h/2];
    49                 y[k]=u+t;
    50                 y[k+h/2]=u-t;
    51                 w=w*wn;
    52             }
    53         }
    54     }
    55     if(on==-1)for(int i=0;i<l;i++) y[i].r/=l;
    56 }
    57 void init(int *a,int n,wjmzbmr *x1,int *b,int m,wjmzbmr *x2)
    58 {
    59     /*将a[0]~a[n-1]放到x1中,将b[0]~b[m-1]放到x2中*/
    60     l=1;
    61     while(l<max(n,m)*2) l<<=1;
    62     for(int i=0;i<n;++i)
    63     {
    64         x1[i].r=a[i];
    65         x1[i].i=0.0;
    66     }
    67     for(int i=n;i<l;++i)x1[i].r=x1[i].i=0.0;
    68     for(int i=0;i<m;++i)
    69     {
    70         x2[i].r=b[i];
    71         x2[i].i=0.0;
    72     }
    73     for(int i=m;i<l;i++) x2[i].r=x2[i].i=0.0;
    74 }
    75 int main()
    76 {
    77     scanf("%d %d",&n,&m);
    78     ++n,++m;
    79     for(int i=0;i<n;++i) scanf("%d",&a[i]);
    80     for(int i=0;i<m;++i) scanf("%d",&b[i]);
    81     init(a,n,x1,b,m,x2);
    82     fft(x1,l,1);
    83     fft(x2,l,1);
    84     for(int i=0;i<l;++i) x1[i]=x1[i]*x2[i];
    85     fft(x1,l,-1);
    86     for(int i=0;i<n+m-1;++i) printf("%lld ",(long long)(x1[i].r+0.5));
    87     return 0;
    88 }
    View Code

    任意模数FFT

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int maxn=524300,mod=1e9+7;
     4 int n;
     5 int A[maxn+5],B[maxn+5],C[maxn+5];
     6 int len;
     7 int pos[maxn+5];
     8 namespace FFT
     9 {
    10     /*
    11     模任意质数mod的FFT
    12     */
    13     const int M=1000;
    14     struct comp
    15     {
    16         long double r,i;
    17         comp(long double _r=0,long double _i=0){r=_r;i=_i;}
    18         comp operator+(const comp x){return comp(r+x.r,i+x.i);}
    19         comp operator-(const comp x){return comp(r-x.r,i-x.i);}
    20         comp operator*(const comp x){return comp(r*x.r-i*x.i,r*x.i+i*x.r);}
    21         comp conj(){return comp(r,-i);}
    22     }A[maxn+5],B[maxn+5];
    23     int a0[maxn+5],b0[maxn+5],a1[maxn+5],b1[maxn+5];
    24     const long double pi=acos(-1.0);
    25     void FFT(comp a[],int n,int t)
    26     {
    27         for(int i=1;i<n;i++)
    28             if(i<pos[i])swap(a[i],a[pos[i]]);
    29         for(int d=0;(1<<d)<n;d++)
    30         {
    31             int m=1<<d,m2=m<<1;
    32             long double o=pi*2/m2*t;comp _w(cos(o),sin(o));
    33             for(int i=0;i<n;i+=m2)
    34             {
    35                 comp w(1,0);
    36                 for(int j=0;j<m;j++)
    37                 {
    38                     comp&A=a[i+j+m],&B=a[i+j],t=w*A;
    39                     A=B-t;B=B+t;w=w*_w;
    40                 }
    41             }
    42         }
    43         if(t==-1)for(int i=0;i<n;i++)a[i].r/=n;
    44     }
    45     void mul(int*a,int*b,int*c,int len)
    46     {//c=a*b
    47         for(int i=0;i<len;i++)A[i]=comp(a[i],b[i]);
    48         FFT(A,len,1);
    49         for(int i=0;i<len;i++)
    50         {
    51             int j=(len-i)&(len-1);
    52             B[i]=(A[i]*A[i]-(A[j]*A[j]).conj())*comp(0,-0.25);
    53         }
    54         FFT(B,len,-1);
    55         for(int i=0;i<len;i++)c[i]=((long long)(B[i].r+0.5))%mod;
    56     }
    57     //输入两个多项式,求a*b mod mod,保存在c中,c不能为a或b,长度为0~len-1
    58     void mulmod(int*a,int*b,int*c,int len)
    59     {
    60         for(int i=0;i<len;i++)a0[i]=a[i]/M,b0[i]=b[i]/M;
    61         mul(a0,b0,a0,len);
    62         for(int i=0;i<len;i++)
    63         {
    64             c[i]=1LL*a0[i]*M*M%mod;
    65             a1[i]=a[i]%M,b1[i]=b[i]%M;
    66         }
    67         mul(a1,b1,a1,len);
    68         for(int i=0;i<len;i++)
    69         {
    70             c[i]=(a1[i]+c[i])%mod,a0[i]=(a0[i]+a1[i])%mod;
    71             a1[i]=a[i]/M+a[i]%M,b1[i]=b[i]/M+b[i]%M;
    72         }
    73         mul(a1,b1,a1,len);
    74         for(int i=0;i<len;i++)c[i]=(1LL*M*(a1[i]-a0[i]+mod)+c[i])%mod;
    75     }
    76 }
    77 int main()
    78 {
    79     for(len=1;len<=n;len<<=1);len<<=1;
    80     int x=__builtin_ctz(len)-1;
    81     for(int i=0;i<len;i++)pos[i]=pos[i>>1]>>1|((i&1)<<x);
    82     for(int i=2;i<=n;i++) A[i]=1LL*pa[n-i]*inv[n-i]%mod;
    83     for(int i=2;i<=n;i++) B[i]=1LL*pb[n-i]*inv[n-i]%mod;
    84     FFT::mulmod(A,B,C,len);
    85     return 0;
    86 }
    View Code

    NTT

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const int maxn=262144*4;
     5 //const long long P=50000000001507329LL; // 190734863287 * 2 ^ 18 + 1
     6 //const int P=1004535809; // 479 * 2 ^ 21 + 1
     7 const ll mod=998244353; // 119 * 2 ^ 23 + 1
     8 const ll G=3;
     9 
    10 ll len=0;
    11 ll pw[maxn+5],pwinv[maxn+5];
    12 ll A[maxn+5],B[maxn+5];
    13 ll f[maxn+5];
    14 int n,m;
    15 
    16 ll Pow(ll a,ll b,ll mod)
    17 {
    18     ll ans=1;
    19     while(b)
    20     {
    21         if(b&1) ans=ans*a%mod;
    22         a=a*a%mod;
    23         b>>=1;
    24     }
    25     return ans;
    26 }
    27 ll Inv(ll x)
    28 {
    29     return Pow(x,mod-2,mod);
    30 }
    31 void Init()
    32 {
    33     ll inv=Inv(G);
    34     for (int i=1;i<=maxn;i<<=1)
    35     {
    36         pw[i]=Pow(G,(mod-1)/i,mod);
    37         pwinv[i]=Pow(inv,(mod-1)/i,mod);
    38     }
    39 }
    40 void rader(ll *a)
    41 {
    42     for(int i=0,j=0;i<len;i++)
    43     {
    44         if(i>j) swap(a[i],a[j]);
    45         int k=len;
    46         do{k>>=1;j^=k;}while(j<k);
    47     }
    48 }
    49 void ntt(ll *a,int f)
    50 {
    51     rader(a);
    52     for(int i=2;i<=len;i<<=1)
    53     {
    54         int m=i>>1;
    55         for(int j=0;j<len;j+=i)
    56         {
    57             ll w=1,wn=pw[i];
    58             if(f==-1) wn=pwinv[i];
    59             for(int k=0;k<m;k++)
    60             {
    61                 ll x=a[j+k+m]*w%mod;
    62                 a[j+k+m]=(a[j+k]-x+mod)%mod;
    63                 a[j+k]=(a[j+k]+x)%mod;
    64                 w=w*wn%mod;
    65             }
    66         }
    67     }
    68     if(f==-1)
    69     {
    70         ll inv=Inv(len);
    71         for(int i=0;i<len;i++) a[i]=a[i]*inv%mod;
    72     }
    73 }
    74 void con(ll *A,int n,ll *B,int m)
    75 {
    76     /*A[0..n-1]与B[0..m-1]卷积*/
    77     for(len=1;len<max(n,m);len<<=1);
    78     len<<=1;
    79     for(int i=n;i<len;++i) A[i]=0;
    80     for(int i=m;i<len;++i) B[i]=0;
    81     ntt(A,1);
    82     ntt(B,1);
    83     for(int i=0;i<len;++i) A[i]=A[i]*B[i]%mod;
    84     ntt(A,-1);
    85 }
    86 int main()
    87 {
    88     Init();
    89     con(A,n,B,m);
    90     return 0;
    91 }
    View Code

    FWT

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int maxn=1024,mod=1e9+7,rev=(mod+1)>>1;
     4 int a[maxn+50],b[maxn+50];
     5 long long fc[maxn*maxn];
     6 int T,n,m;
     7 void fwt(int *a,int n)
     8 {
     9     for(int d=1;d<n;d<<=1)
    10         for(int m=d<<1,i=0;i<n;i+=m)
    11             for(int j=0;j<d;j++)
    12             {
    13                 int x=a[i+j],y=a[i+j+d];
    14                 a[i+j]=(x+y)%mod,a[i+j+d]=(x-y+mod)%mod;
    15                 //xor:a[i+j]=x+y,a[i+j+d]=(x-y+mod)%mod;
    16                 //and:a[i+j]=x+y;
    17                 //or:a[i+j+d]=x+y;
    18             }
    19 }
    20 void ufwt(int *a,int n)
    21 {
    22     for(int d=1;d<n;d<<=1)
    23         for(int m=d<<1,i=0;i<n;i+=m)
    24             for(int j=0;j<d;j++)
    25             {
    26                 int x=a[i+j],y=a[i+j+d];
    27                 a[i+j]=1LL*(x+y)*rev%mod,a[i+j+d]=(1LL*(x-y)*rev%mod+mod)%mod;
    28                 //xor:a[i+j]=(x+y)/2,a[i+j+d]=(x-y)/2;
    29                 //and:a[i+j]=x-y;
    30                 //or:a[i+j+d]=y-x;
    31             }
    32 }
    33 void solve(int *a,int *b,int n)//下标0..n-1的数组a和b求异或卷积,O(nlogn),返回值在a中
    34 {
    35     fwt(a,n);
    36     fwt(b,n);
    37     for(int i=0;i<n;++i) a[i]=1LL*a[i]*b[i]%mod;
    38     ufwt(a,n);
    39 }
    40 int main()
    41 {
    42     fc[0]=1;
    43     for(int i=1;i<=1000000;++i) fc[i]=fc[i-1]*i%mod;
    44     scanf("%d",&T);
    45     while(T--)
    46     {
    47         scanf("%d%d",&n,&m);
    48         memset(a,0,sizeof(a));
    49         memset(b,0,sizeof(b));
    50         for(int i=1;i<=n;++i) a[i]=1;
    51         for(int i=1;i<=m;++i) b[i]=1;
    52         solve(a,b,maxn);
    53         long long ans=1;
    54         for(int i=0;i<maxn;++i) ans=ans*fc[a[i]]%mod;
    55         printf("%lld
    ",ans);
    56     }
    57     return 0;
    58 }
    View Code

    BM算法(模数只能是质数)

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define rep(i,a,n) for (int i=a;i<n;i++)
     4 #define per(i,a,n) for (int i=n-1;i>=a;i--)
     5 #define pb push_back
     6 #define mp make_pair
     7 #define all(x) (x).begin(),(x).end()
     8 #define fi first
     9 #define se second
    10 #define SZ(x) ((int)(x).size())
    11 typedef vector<int> VI;
    12 typedef long long ll;
    13 typedef pair<int,int> PII;
    14 const ll mod=1000000007;
    15 ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
    16 // head
    17 
    18 ll n;
    19 namespace linear_seq {
    20     const int N=10010;
    21     ll res[N],base[N],_c[N],_md[N];
    22 
    23     vector<int> Md;
    24     void mul(ll *a,ll *b,int k) {
    25         rep(i,0,k+k) _c[i]=0;
    26         rep(i,0,k) if (a[i]) rep(j,0,k) _c[i+j]=(_c[i+j]+a[i]*b[j])%mod;
    27         for (int i=k+k-1;i>=k;i--) if (_c[i])
    28             rep(j,0,SZ(Md)) _c[i-k+Md[j]]=(_c[i-k+Md[j]]-_c[i]*_md[Md[j]])%mod;
    29         rep(i,0,k) a[i]=_c[i];
    30     }
    31     int solve(ll n,VI a,VI b) { // a 系数 b 初值 b[n+1]=a[0]*b[n]+...
    32 //        printf("%d
    ",SZ(b));
    33         ll ans=0,pnt=0;
    34         int k=SZ(a);
    35         assert(SZ(a)==SZ(b));
    36         rep(i,0,k) _md[k-1-i]=-a[i];_md[k]=1;
    37         Md.clear();
    38         rep(i,0,k) if (_md[i]!=0) Md.push_back(i);
    39         rep(i,0,k) res[i]=base[i]=0;
    40         res[0]=1;
    41         while ((1ll<<pnt)<=n) pnt++;
    42         for (int p=pnt;p>=0;p--) {
    43             mul(res,res,k);
    44             if ((n>>p)&1) {
    45                 for (int i=k-1;i>=0;i--) res[i+1]=res[i];res[0]=0;
    46                 rep(j,0,SZ(Md)) res[Md[j]]=(res[Md[j]]-res[k]*_md[Md[j]])%mod;
    47             }
    48         }
    49         rep(i,0,k) ans=(ans+res[i]*b[i])%mod;
    50         if (ans<0) ans+=mod;
    51         return ans;
    52     }
    53     VI BM(VI s) {
    54         VI C(1,1),B(1,1);
    55         int L=0,m=1,b=1;
    56         rep(n,0,SZ(s)) {
    57             ll d=0;
    58             rep(i,0,L+1) d=(d+(ll)C[i]*s[n-i])%mod;
    59             if (d==0) ++m;
    60             else if (2*L<=n) {
    61                 VI T=C;
    62                 ll c=mod-d*powmod(b,mod-2)%mod;
    63                 while (SZ(C)<SZ(B)+m) C.pb(0);
    64                 rep(i,0,SZ(B)) C[i+m]=(C[i+m]+c*B[i])%mod;
    65                 L=n+1-L; B=T; b=d; m=1;
    66             } else {
    67                 ll c=mod-d*powmod(b,mod-2)%mod;
    68                 while (SZ(C)<SZ(B)+m) C.pb(0);
    69                 rep(i,0,SZ(B)) C[i+m]=(C[i+m]+c*B[i])%mod;
    70                 ++m;
    71             }
    72         }
    73         return C;
    74     }
    75     int gao(VI a,ll n) {
    76         VI c=BM(a);
    77         c.erase(c.begin());
    78         rep(i,0,SZ(c)) c[i]=(mod-c[i])%mod;
    79         return solve(n,c,VI(a.begin(),a.begin()+SZ(c)));
    80     }
    81 };
    82 vector<int> a;
    83 int main() {
    84     int T;
    85     scanf("%d",&T);
    86     a.clear();
    87     a.pb(31),a.pb(197),a.pb(1255),a.pb(7997),a.pb(50959),a.pb(324725);
    88     while(T--)
    89     {
    90         scanf("%lld",&n);
    91         printf("%d
    ",linear_seq::gao(a,n-1));
    92     }
    93     return 0;
    94 }
    View Code

    k^2logn求线性递推

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int maxn=4000,mod=1000000007;
     4 int a[maxn+5],p[maxn+5],ans[maxn+5],num[maxn+5];
     5 int h[maxn+5],tmp[maxn+5];
     6 int n,k;
     7 void mul(int *a,int *b,int *ans)
     8 {
     9     for(int i=0;i<=2*k;++i) tmp[i]=0;
    10     for(int i=0;i<k;++i)
    11         for(int j=0;j<k;++j)
    12             tmp[i+j]=(tmp[i+j]+1LL*a[i]*b[j])%mod;
    13     for(int i=2*k-2;i>=k;--i)
    14     {
    15         for(int j=k-1;j>=0;--j)
    16             tmp[i-k+j]=(tmp[i-k+j]-1LL*tmp[i]*p[j])%mod,tmp[i-k+j]=(tmp[i-k+j]+mod)%mod;
    17         tmp[i]=0;
    18     }
    19     for(int i=0;i<k;++i) ans[i]=tmp[i];
    20 }
    21 int main()
    22 {
    23     scanf("%d%d",&n,&k);
    24     for(int i=1;i<=k;++i) scanf("%d",&a[i]);
    25     for(int i=0;i<k;++i) scanf("%d",&h[i]);
    26     p[k]=1;
    27     for(int i=1;i<=k;++i) p[k-i]=mod-a[i];
    28     for(int i=k;i<2*k;++i)
    29         for(int j=1;j<=k;++j)
    30         {
    31             h[i]=h[i]+1LL*h[i-j]*a[j]%mod;
    32             h[i]%=mod;
    33         }
    34     if(n<2*k) return 0*printf("%d
    ",h[n]);
    35     int b=n-k+1;
    36     num[1]=1,ans[0]=1;
    37     while(b)
    38     {
    39         if(b&1) mul(ans,num,ans);
    40         mul(num,num,num);
    41         b>>=1;
    42     }
    43     long long res=0;
    44     for(int i=0;i<k;++i) res=(res+1LL*ans[i]*h[i+k-1])%mod;
    45     printf("%lld
    ",(res+mod)%mod);
    46     return 0;
    47 }
    View Code

    lagrange插值

     1 void mul(int *a,int d,int c)
     2 {
     3     /*
     4     a*(x-c)
     5     */
     6     int b[maxn+5];
     7    // memset(b,0,sizeof(b));
     8     for(int i=0;i<=d;++i) b[i]=a[i];
     9     for(int i=d+1;i>=1;--i) a[i]=a[i-1];
    10     a[0]=0;
    11     for(int i=0;i<=d;++i)
    12     {
    13         a[i]=(a[i]-1LL*b[i]*c)%mod;
    14         if(a[i]<0) a[i]+=mod;
    15     }
    16 }
    17 void div(int *a,int d,int c,int *ans)
    18 {
    19     /*
    20     ans=a/(x-c)
    21     */
    22     ans[d-1]=a[d];
    23     for(int i=d-2;i>=0;--i)
    24         ans[i]=(a[i+1]+1LL*c*ans[i+1])%mod;
    25 }
    26 void lagrange(int *y,int d,int *p)
    27 {
    28     /*
    29     (0,y[0]),(1,y[1]),...,(d,y[d])
    30     插出的系数放p中
    31     */
    32     int tmp[maxn+5],now[maxn+5];
    33     memset(tmp,0,sizeof(tmp));
    34     memset(now,0,sizeof(now));
    35     tmp[0]=1;
    36     for(int i=0;i<=d;++i)
    37     {
    38         mul(tmp,i,i);
    39     }
    40     for(int i=0;i<=d;++i)
    41     {
    42         for(int j=0;j<=d;++j) now[j]=0;
    43         div(tmp,d+1,i,now);
    44         long long q=1;
    45         for(int j=0;j<=d;++j)
    46             if(i!=j)
    47             {
    48                 q=q*(i-j)%mod;
    49                 if(q<0) q+=mod;
    50             }
    51         q=inv(q);
    52         q=q*y[i]%mod;
    53         for(int j=0;j<=d;++j) now[j]=1LL*now[j]*q%mod;
    54         for(int j=0;j<=d;++j) p[j]=(p[j]+now[j])%mod;
    55     }
    56 }
    View Code

    高斯消元

     1 /*
     2 n个未知数,m个方程
     3 */
     4 #include<bits/stdc++.h>
     5 using namespace std;
     6 const int maxn=1000;
     7 const double eps=1e-6;
     8 double a[maxn+5][maxn+5];
     9 int n,m;
    10 int main()
    11 {
    12     scanf("%d%d",&n,&m);
    13     for(int i=1;i<=m;++i)
    14         for(int j=1;j<=n+1;++j)
    15             scanf("%lf",&a[i][j]);
    16     for(int i=1;i<=n;++i)//枚举列
    17     {
    18         if(fabs(a[i][i]-0.0)<=eps)
    19         {
    20             int j;
    21             bool flag=0;
    22             for(j=i+1;j<=m;++j)
    23                 if(fabs(a[j][i]-0.0)>eps)
    24                 {
    25                     flag=1;
    26                     break;
    27                 }
    28             if(!flag) return 0*printf("Many solutions");//如果第i~m行的第i列都是0,那么多解
    29             for(int k=1;k<=n+1;++k) swap(a[i][k],a[j][k]);
    30         }
    31         for(int j=1;j<=n+1;++j) if(i!=j)a[i][j]/=a[i][i];a[i][i]=1.0;
    32         for(int j=1;j<=m;++j)
    33             if(j!=i)
    34             {
    35                 for(int k=1;k<=n+1;++k) if(k!=i) a[j][k]-=a[i][k]*a[j][i];a[j][i]=0.0;
    36             }
    37     }
    38     for(int i=n+1;i<=m;++i)
    39         if(fabs(a[i][n+1]-0.0)>eps) return 0*printf("No solutions");//n+1~m这些方程应该所有变量都被消干净了,所以如果不为0,则说明无解
    40     for(int i=1;i<=n;++i) printf("%d
    ",(int)(a[i][n+1]+0.5));
    41     return 0;
    42 }
    View Code

    求行列式

     1 const int maxn=1000;
     2 ll a[maxn+5][maxn+5];
     3 int turn,n;
     4 void gcd(ll a,ll b,ll &d,ll &x,ll &y)
     5 {
     6     if(!b) d=a,x=1,y=0;
     7     else
     8     {
     9         ++turn;
    10         gcd(b,a%b,d,y,x);
    11         y-=x*(a/b);
    12     }
    13 }
    14 ll det(ll n)
    15 {
    16     //求行列式a[0..n-1][0..n-1]
    17     ll tmp1[maxn+5],tmp2[maxn+5];
    18     ll ans=1;
    19     for(int i=0;i<n;++i)
    20     {
    21         for(int j=i+1;j<n;++j)
    22             if(a[j][i]!=0)
    23             {
    24                 ll A=a[i][i],B=a[j][i],d,x,y;
    25                 turn=0;
    26                 gcd(A,B,d,x,y);
    27                 for(int k=0;k<n;++k) tmp1[k]=a[i][k],tmp2[k]=a[j][k];
    28                 for(int k=0;k<n;++k) a[i][k]=(x*tmp1[k]+y*tmp2[k])%mod;
    29                 A/=d,B/=d;
    30                 if(turn&1) x=B,y=-A,ans=-ans%mod;else x=-B,y=A;
    31                 for(int k=0;k<n;++k) a[j][k]=(x*tmp1[k]+y*tmp2[k])%mod;
    32             }
    33         ans=ans*a[i][i]%mod;
    34     }
    35     if(ans<0) ans+=mod;
    36     return ans;
    37 }
    View Code

    计算几何

    求凸包

     1 #include<cstring>
     2 #include<algorithm>
     3 #include<cstdio>
     4 using namespace std;
     5 const int maxn=50000;
     6 struct wjmzbmr
     7 {
     8     int x,y;
     9     bool operator < (const wjmzbmr& a) const
    10     {
    11         return (x<a.x)||(x==a.x&&y<a.y);
    12     }
    13 }a[maxn+50];
    14 int n,s[maxn+50],q[maxn+50],m=0,len=0;
    15 int cross(int x1,int y1,int x2,int y2)
    16 {
    17     return (x1*y2-y1*x2);
    18 }
    19 int main()
    20 {
    21     scanf("%d",&n);
    22     for(int i=1;i<=n;++i) scanf("%d %d",&a[i].x,&a[i].y);
    23     sort(a+1,a+n+1);
    24     m=2;
    25     s[1]=1,s[2]=2;
    26     for(int i=3;i<=n;++i)
    27     {
    28         while(m>=2&&cross(a[s[m]].x-a[s[m-1]].x,a[s[m]].y-a[s[m-1]].y,a[i].x-a[s[m]].x,a[i].y-a[s[m]].y)<=0) --m;
    29         s[++m]=i;
    30     }
    31     s[++m]=n-1;
    32     int k=m;
    33     for(int i=n-2;i>=1;--i)
    34     {
    35         while(m>=k&&cross(a[s[m]].x-a[s[m-1]].x,a[s[m]].y-a[s[m-1]].y,a[i].x-a[s[m]].x,a[i].y-a[s[m]].y)<=0) --m;
    36         s[++m]=i;
    37     }
    38     int ans=0;
    39     for(int i=1;i<=m-1;++i)
    40         for(int j=i+1;j<=m;++j)
    41             if((a[s[i]].x-a[s[j]].x)*(a[s[i]].x-a[s[j]].x)+(a[s[i]].y-a[s[j]].y)*(a[s[i]].y-a[s[j]].y)>ans) ans=(a[s[i]].x-a[s[j]].x)*(a[s[i]].x-a[s[j]].x)+(a[s[i]].y-a[s[j]].y)*(a[s[i]].y-a[s[j]].y);
    42     printf("%d",ans);
    43     return 0;
    44 }
    View Code

    自适应辛普森

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const double eps=1e-6;
     4 double a,b,l,r;
     5 double F(double x)
     6 {
     7     //Simpson公式用到的函数
     8     return 2*sqrt(b*b-b*b*x*x/a/a);
     9 }
    10 double simpson(double l,double r)//三点Simpson法,这里要求F是一个全局函数
    11 {
    12     double mid=(l+r)*0.5;
    13     return (F(l)+4*F(mid)+F(r))*(r-l)/6;
    14 }
    15 double asr(double l,double r)//自适应Simpson公式(递归过程)
    16 {
    17     double mid=(l+r)*0.5;
    18     double x=simpson(l,mid),y=simpson(mid,r);
    19     double z=simpson(l,r);
    20     if(fabs(x+y-z)<=15*eps) return x+y+(x+y-z)/15.0;
    21     return asr(l,mid)+asr(mid,r);
    22 }
    23 int main()
    24 {
    25     int T;
    26     scanf("%d",&T);
    27     while(T--)
    28     {
    29         scanf("%lf%lf%lf%lf",&a,&b,&l,&r);
    30         printf("%.3f
    ",asr(l,r));
    31     }
    32     return 0;
    33 }
    View Code

    chelly的计算几何模板

     1 typedef double db;
     2 const db eps=1e-12;
     3 struct Point
     4 {
     5     /*点类*/
     6     db x,y;
     7     Point(){}
     8     Point(db _x,db _y):x(_x),y(_y){}
     9     Point operator + (const Point &t)const
    10     {
    11         return Point(x+t.x,y+t.y);
    12     }
    13     Point operator - (const Point &t)const
    14     {
    15         return Point(x-t.x,y-t.y);
    16     }
    17     Point operator * (const db &t)const
    18     {
    19         return Point(x*t,y*t);
    20     }
    21     Point operator / (const db &t)const
    22     {
    23         return Point(x/t,y/t);
    24     }
    25     db operator * (const Point &t)const
    26     {
    27         return x*t.y-y*t.x;
    28     }
    29     db len()const
    30     {
    31         return sqrtl(x*x+y*y);
    32     }
    33     Point rot90()const
    34     {
    35         return Point(-y,x);
    36     }
    37 };
    38 struct Complex
    39 {
    40     /*复数类,用于旋转*/
    41     db x,y;
    42     Complex(db x=0.0,db y=0.0):x(x),y(y){}
    43     Complex operator + (const Complex &t)const
    44     {
    45         return Complex(x+t.x,y+t.y);
    46     }
    47     Complex operator - (const Complex &t)const
    48     {
    49         return Complex(x-t.x,y-t.y);
    50     }
    51     Complex operator * (const Complex &t)const
    52     {
    53         return Complex(x*t.x-y*t.y,x*t.y+y*t.x);
    54     }
    55     Complex operator / (const Complex &t)const
    56     {
    57         return Complex((x*t.x+y*t.y)/(t.x*t.x+t.y*t.y),(y*t.x-x*t.y)/(t.x*t.x+t.y*t.y));
    58     }
    59 };
    60 struct Circle
    61 {
    62     /*圆类*/
    63     Point o;
    64     db r;
    65     Circle(){}
    66     Circle(Point _o,db _r):o(_o),r(_r){}
    67     friend vector<Point> operator & (const Circle &c1,const Circle &c2)
    68     {
    69         /*
    70         若两圆相离,返回空
    71         若两圆相切,返回两个相同的点
    72         若两圆相交,返回两个不同的点
    73         */
    74         db d=(c1.o-c2.o).len();
    75         if(d>c1.r+c2.r+eps||d<fabs(c1.r-c2.r)-eps) return vector<Point>();
    76         db dt=(c1.r*c1.r-c2.r*c2.r)/d,d1=(d+dt)/2;
    77         Point dir=(c2.o-c1.o)/d,pcrs=c1.o+dir*d1;
    78         dt=sqrt(max(0.0L,c1.r*c1.r-d1*d1)),dir=dir.rot90();
    79         return vector<Point>{pcrs+dir*dt,pcrs-dir*dt};
    80     }
    81 };
    82 void calcentre()
    83 {
    84     /*
    85     计算凸多边形的重心
    86     将凸多边形划分成若干小三角形,求出三角形的重心,然后根据小三角形面积求加权平均
    87     */
    88     db area=0.0;
    89     for(int i=2;i<n;++i) area+=(a[i+1]-a[i])*(a[1]-a[i]);
    90     g=Point(0,0);
    91     for(int i=2;i<n;++i)
    92     {
    93         db s=(a[i+1]-a[i])*(a[1]-a[i]);
    94         g=g+(a[1]+a[i]+a[i+1])/3.0*(s/area);
    95     }
    96 }
    View Code

     ABerror计算几何

    namespace Geometry {
    	using namespace std;
    	const double INF = 1e100;
    	const double EPS = 1e-12;
    	const double PI = acos(-1.0);
    	typedef complex<double> Pt;
    	typedef vector<Pt> Poly;
    	Pt IJ = Pt(0, 1);
    	int dcmp(double db) {
    		if (db < -EPS)return -1;
    		else return db > EPS;
    	}
    	int dcmp(double A, double B) {
    		return dcmp(A - B);
    	}
    	double cross(const Pt &A, const Pt &B) { return imag(conj(A) * B); }
    	double dot(const Pt &A, const Pt &B) { return real(conj(A) * B); }
    	double angle(const Pt &A) { return atan2(A.imag(), A.real()); }
    	Pt rotate(const Pt &A, double angle) { return A * exp(Pt(0, angle)); }
    	typedef struct Seg {
    		Pt A, B;
    		Seg(
    			double x1 = 0,
    			double y1 = 0,
    			double x2 = 0,
    			double y2 = 0
    		) :A(x1, y1), B(x2, y2) {
    			;
    		}
    		Seg(Pt A, Pt B) :A(A), B(B) { ; }
    		Pt vec()const { return B - A; }
    		bool operator<(const Seg & other)const {
    			return dcmp(angle(vec()) - angle(other.vec())) < 0;
    		}
    	}Line;
    
    	///////////////////////////////////////////////////////////////
    	//函数 :bool SegSegInterset(Seg fst, Seg sec, Pt &P)
    	//功能 :计算前两条直线的交点并返回是否有交点
    	//		如果需要计算交点,就在P处返回
    	//注意 :需要提前处理共线情况
    	///////////////////////////////////////////////////////////////
    	bool SegSegInterset(Seg fst, Seg sec) {
    		assert(dcmp(cross(fst.vec(), sec.vec())) != 0);
    		double p1 = cross(fst.A - sec.A, sec.vec());
    		double p2 = cross(fst.B - sec.A, sec.vec());
    		double p3 = cross(sec.A - fst.A, fst.vec());
    		double p4 = cross(sec.B - fst.A, fst.vec());
    		return dcmp(p1 * p2) <= 0 && dcmp(p3 * p4) <= 0;
    	}
    	bool SegSegInterset(Seg fst, Seg sec, Pt &P) {
    		if (SegSegInterset(fst, sec)) {
    			Pt A = fst.A, B = sec.A;
    			Pt a = fst.B - fst.A, b = sec.B - sec.A;
    			double t1 = cross(A - B, b) / cross(b, a);
    			P = A + a * t1;
    			return true;
    		}
    		else return false;
    	}
    	bool LineLineInterset(Line fst, Line sec, Pt& P) {
    		if (dcmp(cross(fst.vec(), sec.vec())) != 0) {
    			Pt A = fst.A, B = sec.A;
    			Pt a = fst.B - fst.A, b = sec.B - sec.A;
    			double t1 = cross(A - B, b) / cross(b, a);
    			P = A + a * t1;
    			return true;
    		}
    		else
    			exit(0xf0f00000);
    	}
    
    	///////////////////////////////////////////////////////////////
    	//函数 :	Poly& convex(vector<Pt> &pts)
    	//功能 :	计算pts里的凸包并返回(逆时针排序)
    	//注意 :	返回值保存在pts里面
    	//		这个函数假设了一定存在凸包,对于点全部共线或者重合未定义
    	///////////////////////////////////////////////////////////////
    	Pt cmpPt; Seg cmpSeg;
    	bool cmp(Pt A, Pt B) {
    		A = A - cmpPt; B = B - cmpPt;
    		if (dcmp(cross(A, B)) != 0)
    			return dcmp(cross(A, B)) > 0;
    		else
    			return dcmp(abs(A) - abs(B)) < 0;
    	}
    	Poly& convex(vector<Pt> &pts) {
    		int pos = 0;
    		rep(i, 0, (int)pts.size()) {
    			Pt &e = pts[i];
    			if (dcmp(e.real() - pts[pos].real())  < 0 ||
    				dcmp(e.real() - pts[pos].real()) == 0 &&
    				dcmp(e.imag() - pts[pos].imag())  < 0
    				) {
    				pos = i;
    			}
    		}
    		vector<Pt> ans;
    		ans.push_back(pts[pos]);
    		cmpPt = pts[pos];
    		pts.erase(pts.begin() + pos);
    		sort(pts.begin(), pts.end(), cmp);
    		rep(j, 0, pts.size()) {
    			Pt &i = pts[j];
    			while (ans.size() >= 2u &&
    				cross(
    					ans[ans.size() - 1] - ans[ans.size() - 2],
    					i - ans[ans.size() - 2]
    				) <= 0) {
    				ans.pop_back();
    			}
    			ans.push_back(i);
    		}
    		return pts = ans;
    	}
    
    	///////////////////////////////////////////////////
    	//函数:	Poly HalfPlaneIntersect(vector<Seg> seg)
    	//功能:	半平面交
    	//注意:	1. 这个程序不能判断交集为一个点的情况
    	//		2. 如果真的遇见这种情况,可以把所有边右移 1~2 个EPS
    	///////////////////////////////////////////////////
    	inline bool OnLeft(const Line & line, Pt pt) {
    		return dcmp(cross(line.vec(), pt - line.A)) > 0;
    	}
    	Poly HalfPlaneIntersect(vector<Seg> seg) {
    		vector<Seg> s(seg.size() + 5);
    		vector<Pt> p(seg.size() + 5);
    		int N = (int)seg.size(), l = 0, r = 0;
    		sort(seg.begin(), seg.end());
    		s[r++] = seg[0];
    		rep(i, 1, N) {
    			//tips:这里会弹出在直线上方的点,因此不能处理最后的解为一个点的情况
    			while (r - l >= 2 && !OnLeft(seg[i], p[r - 1]))r--;
    			while (r - l >= 2 && !OnLeft(seg[i], p[l + 1]))l++;
    			s[r++] = seg[i];
    			if (dcmp(cross(s[r - 1].vec(), s[r - 2].vec())) == 0) {
    				//exit(0xf0f00011);//debug
    				//如果最后一条线在倒数第二条线的左边,则挑选这条线
    				if (OnLeft(s[r - 2], s[r - 1].A))
    					s[r - 2] = s[r - 1];
    				r--;
    			}
    			//如果符合了上述情况,下面这个语句会发生重新求交
    			//如果不符合,这个语句会求新的交点
    			//注意由于上面那个语句,使得半平面的数量少于2,因此要作判断
    			if (r - l >= 2)
    				LineLineInterset(s[r - 2], s[r - 1], p[r - 1]);
    		}
    		//注意,下面这个部分对于判断交集是否为空有重大作用
    		//如果要起到这个作用,交点在s[l]上的时候也应该被弹出
    		while (r - l >= 2 && !OnLeft(s[l], p[r - 1]))r--;
    		if (r - l <= 2)return Poly();//无交集返回空集
    		LineLineInterset(s[r - 1], s[l], p[l]);
    		return Poly(p.begin() + l, p.begin() + r);
    	}
    	///////////////////////////////////////////////////
    	//函数:	bool PtOnSeg(Pt p, Seg seg) 
    	//功能:	判断点在线段上
    	//注意:	在该程序中,在线段的两个端点上也算在线段上
    	///////////////////////////////////////////////////
    	bool PtOnSeg(Pt p, Seg seg) {
    		//判断共直线
    		Pt l = seg.vec();
    		assert(dcmp(abs(l)) != 0);
    		if (dcmp(cross(l, p - seg.A)) != 0)return false;
    		double d = dot(p - seg.A, l);
    		return dcmp(d) >= 0 && dcmp(d - dot(l, l)) <= 0;
    	}
    	///////////////////////////////////////////////////
    	//函数:	int PtInPolygon(const Pt P, const Poly &poly) 
    	//功能:	询问点是否在多边形内部
    	///////////////////////////////////////////////////
    	int PtInPolygon(const Pt P, const Poly &poly) {
    		int N = (int)poly.size();
    		double sum = 0;
    		rep(i, 0, N) {
    			//判断在交点上
    			if (dcmp(abs(P - poly[i])) == 0)
    				return 1;
    			//判断在线段上
    			if (PtOnSeg(P, Seg(poly[i], poly[(i + 1) % N])))
    				return 2;
    			Pt A = poly[i] - P;
    			Pt B = poly[(i + 1) % N] - P;
    			sum += angle(rotate(B, -angle(A)));
    		}
    		//判断在多边形内部,无论的逆时针还是顺时针都可以进行判断
    		return 3 * (dcmp(sum - 2 * PI) == 0 || dcmp(sum + 2 * PI) == 0);
    	}
    	///////////////////////////////////////////////////
    	//函数:double PtLineDistance(Pt P, Line L)
    	//功能: 计算点到直线上的距离
    	///////////////////////////////////////////////////
    	double PtLineDistance(Pt P, Line L) {
    		Pt v = L.vec();
    		return fabs(cross(P - L.A, v)) / abs(v);
    	}
    	///////////////////////////////////////////////////
    	//函数:	Pt PtLineProjection(Pt P, Line L)
    	//功能:	计算点在直线上的投影
    	///////////////////////////////////////////////////
    	Pt PtLineProjection(Pt P, Line L) {
    		Pt v = L.vec();
    		return L.A + v * dot(P - L.A, v) / dot(v, v);
    	}
    	///////////////////////////////////////////////////
    	//函数:	double PtSegDistance(Pt P, Seg s)
    	//功能:	计算点到线段的距离
    	///////////////////////////////////////////////////
    	double PtSegDistance(Pt P, Seg s) {
    		double AB = abs(s.vec());
    		double d = dot(P - s.A, s.vec() / AB);	//AP在于AB方向单位向量点积
    		if (dcmp(d) >= 0 && dcmp(d - AB) <= 0) {//等于AP在AB方向投影长度
    			return PtLineDistance(P, s);		//如果这个长度在0到|AB|之间
    		}
    		else return min(abs(P - s.A), abs(P - s.B));
    	}
    	/*************************************************************/
    	/////////////////////////////////////////////////////
    	//圆的部分(圆和圆弧)
    	//数据结构:	Cir/Circle	圆
    	//			Arc			圆弧
    	/////////////////////////////////////////////////////
    	typedef struct Cir {
    		Pt P;		//圆心
    		double R;	//半径
    		Cir(Pt P = Pt(), double R = 0) :P(P), R(R) { ; }
    		Pt pt(double angle) {
    			return P + R * exp(angle * IJ);
    		}
    	}Circle;
    	struct Arc :public Cir {
    		double l, r;//角度在[l,r]范围内
    		Arc(double l = 0, double r = 0, Cir C = Cir()) :
    			l(l), r(r), Cir(C) {
    			;
    		}
    	};
    	/////////////////////////////////////////////////////
    	//函数:	LineCirIntersect(Line L, Cir C)
    	//功能:
    	//		直线和圆的交点
    	//		以Poly的形式返回直线和圆的交点的集合
    	//		有几个就返回几个
    	/////////////////////////////////////////////////////
    	Poly LineCirIntersect(Line L, Cir C) {
    		Poly ret;
    		double dis = PtLineDistance(C.P, L);
    		Pt Pjt = PtLineProjection(C.P, L);
    		Pt v = L.vec();
    		switch (dcmp(dis - C.R)) {
    			//相交
    		case -1:
    			v = v / abs(v) * sqrt(C.R * C.R - dis * dis);
    			ret.push_back(Pjt - v);
    			ret.push_back(Pjt + v);
    			//相切,就放进去投影点
    		case 0:ret.push_back(Pjt); break;
    			//相离,直接退出
    		case 1:break;
    		default:exit(0xf0f00002);
    		}
    		return ret;
    	}
    	///////////////////////////////////////////////////
    	//函数:	bool PtOnArc(const Pt p,const Arc &arc)
    	//功能:	判断点在圆弧上
    	//注意:	1. 这个函数默认点在圆上,用于判定是否在圆弧上
    	//		2. 如果在圆弧端点上,认为在圆弧上
    	///////////////////////////////////////////////////
    	bool PtOnArc(const Pt p, const Arc &arc) {
    		double ang = angle(p - arc.P);
    		assert(dcmp(arc.l - arc.r) != 0);
    		if (arc.l < arc.r)
    			return dcmp(ang - arc.l) >= 0 && dcmp(ang - arc.r) <= 0;
    		else
    			return dcmp(ang - arc.l) >= 0 || dcmp(ang - arc.r) <= 0;
    	}
    	///////////////////////////////////////////////////
    	//函数:	Poly SegArcIntersect(Seg S, Arc A)
    	//功能:	计算线段和圆弧的交点
    	//注意:	有几个交点就返回几个交点
    	///////////////////////////////////////////////////
    	Poly SegArcIntersect(Seg S, Arc A) {
    		Poly ret = LineCirIntersect(S, A);
    		for (int i = (int)ret.size() - 1; i >= 0; i--) {
    			if (!PtOnSeg(ret[i], S) || !PtOnArc(ret[i], A))
    				ret.erase(ret.begin() + i);
    		}
    		return ret;
    	}
    	///////////////////////////////////////////////////
    	//函数:	Poly CirCirIntersect(Cir A, Cir B)
    	//功能:	两圆相交,计算交点,这里只是计算交点,不讨论类型
    	//注意:	某些情况下,要判断5种情况,设两圆半径r <= R,圆心距d
    	//		1.相离,R + r - d < 0
    	//		2.外切,R + r - d = 0
    	//		3.相交,R + r - d > 0 && R - r - d < 0
    	//		4.内切,R - r - d = 0
    	//		5.内含,R - r - d > 0
    	//		6.重合,R = r,d = 0
    	///////////////////////////////////////////////////
    	Poly CirCirIntersect(Cir A, Cir B) {
    		Poly ret;
    		if (A.R < B.R)swap(A, B);
    		Pt AB = B.P - A.P;
    		double R = A.R, r = B.R, d = abs(AB);
    		double cmp1 = dcmp(R + r - d), cmp2 = dcmp(R - r - d);
    		assert(!(dcmp(R - r) == 0 && dcmp(d) == 0));
    		if (cmp1 == 0 || cmp2 == 0) {
    			ret.push_back(A.P + AB * R / d);
    		}
    		else if (cmp1 > 0 && cmp2 < 0) {
    			double theta = angle(AB);
    			double alpha = acos((R * R + d * d - r * r) / (2 * R * d));
    			ret.push_back(A.P + R * exp((theta + alpha) * IJ));
    			ret.push_back(A.P + R * exp((theta - alpha) * IJ));
    		}
    		return ret;
    	}
    	///////////////////////////////////////////////////
    	//函数:	Poly ArcArIntersect(Arc A, Arc B)
    	//功能:	计算两个圆弧的交点,有几个输出几个
    	//注意:
    	///////////////////////////////////////////////////
    	Poly ArcArcIntersect(Arc A, Arc B) {
    		Poly ret = CirCirIntersect(A, B);
    		for (int i = (int)ret.size() - 1; i >= 0; i--) {
    			if (!PtOnArc(ret[i], A) || !PtOnArc(ret[i], B))
    				ret.erase(ret.begin() + i);
    		}
    		return ret;
    	}
    };
    

      

    其它科技

    手写bitset

     1 struct Bitset
     2 {
     3     /*32位压成一个unsigned int,最多压8个*/
     4     unsigned int a[8];
     5     void clear()
     6     {
     7         for(int i=0;i<8;++i) a[i]=0;
     8     }
     9     void set(int x)
    10     {
    11         /*第x位置1*/
    12         a[x>>5]|=1U<<(x&31);
    13         /*
    14         x>>5即x/32,确定x在哪个数组里
    15         x&31即x%32,确定x在对应数组里的第几小位
    16         */
    17     }
    18     void flip(int x)
    19     {
    20         /*将第x位反转*/
    21         a[x>>5]^=1U<<(x&31);
    22     }
    23     int get(int x)
    24     {
    25         /*返回第x位的值0/1*/
    26         return a[x>>5]&(1U<<(x&31));
    27     }
    28 }num;
    29 //手写bitset的强大之处就是可以快速取出所有是1的位置,不过其实bitset里也封装了_Find_first()和_Find_next(x)
    30 for(int i=0;i<8;++i)
    31 {
    32     while(true)
    33     {
    34         if(!num.a[i]) break;
    35         int p=__builtin_ctz(num.a[i]);//__builtin_ctz(unsigned int x) 是通过O(1)的时间返回数字x最右边连续0的个数
    36         printf("%d
    ",i<<5|p);
    37         num.flip(i<<5|p);
    38     }
    39 }
    40 //手写bitset还可以取出连续的一段区间,但是封装的却不行
    41 void make(int l,int r)
    42 {
    43     int shift=l&31;
    44     int y=(r-l)>>5;
    45     int j=l>>5;
    46     for(int i=0;i<y;++i)
    47     {
    48         u num=(a.num[j]>>shift);
    49         if(shift!=0) num|=a.num[j+1]<<(32-shift);//注意x<<32并不是0,而是x本身
    50         ans.num[i]^=num;
    51         ++j;
    52     }
    53     for(int i=l+32*y;i<=r;++i)
    54         if(a.get(i))
    55             ans.flip(i-l);
    56 }
    View Code

    决策单调性优化

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int maxn=200,inf=1e7;
     4 int a[maxn+50],f[maxn+50][50+5];
     5 int kk[maxn+50][50+5];
     6 int m,s,n;
     7 struct wjmzbmr
     8 {
     9     int l,r,p;
    10 }q[maxn+50];
    11 int cal(int j,int i,int p)
    12 {
    13     return f[p][j]+a[i]-a[p+1]+1;
    14 }
    15 int find(int j,int l,int r,int p,int pp)
    16 {
    17     int mid;
    18     bool flag=0;
    19     while(l<r)
    20     {
    21         mid=(l+r)>>1;
    22         if(cal(j-1,mid,p)>cal(j-1,mid,pp)) l=mid+1;else r=mid;
    23     }
    24     if(cal(j-1,r,p)<cal(j-1,r,pp)) return r;else return r+1;
    25 }
    26 int main()
    27 {
    28     scanf("%d%d%d",&m,&s,&n);
    29     for(int i=1;i<=n;++i) scanf("%d",&a[i]);
    30     sort(a+1,a+n+1);
    31     for(int i=0;i<=n;++i)
    32         for(int j=0;j<=m;++j)
    33             f[i][j]=inf;
    34     memset(f[0],0,sizeof(f[0]));
    35     for(int i=1;i<=n;++i) f[i][1]=a[i]-a[1]+1;
    36     for(int j=2;j<=m;++j)
    37     {
    38         int head=1,tail=1;
    39         q[1]={1,n,0};
    40         for(int i=1;i<=n;++i)
    41         {
    42             while(head<tail&&q[head].r<i) ++head;
    43             f[i][j]=cal(j-1,i,q[head].p);
    44             while(head<tail&&cal(j-1,q[tail].l,i)<cal(j-1,q[tail].l,q[tail].p)) --tail;
    45             int position=find(j,q[tail].l,q[tail].r,i,q[tail].p);
    46             if(position<=n)
    47             {
    48                 q[tail+1]={position,n,i};
    49                 q[tail].r=position-1;
    50                 if(q[tail].l>q[tail].r) ++head;
    51                 ++tail;
    52             }
    53         }
    54     }
    55     printf("%d
    ",f[n][m]);
    56     return 0;
    57 }
    View Code

    数位DP

     1 //数位dp的每个数字都在它的前缀处统计,所以每次dp的数字其实是一个前缀
     2 #include<bits/stdc++.h>
     3 using namespace std;
     4 #define mp make_pair
     5 typedef long long ll;
     6 const ll mod=998244353;
     7 pair<ll,ll> dp[19][1024];   //first记录满足条件的数字个数,second记录满足条件的数字之和
     8 int a[19];
     9 int d;
    10 ll pw[20];
    11 long long n;
    12 void update(ll &a,ll b)
    13 {
    14     a=(a+b)%mod;
    15 }
    16 pair<ll,ll> dfs(int len,int ok,bool flag,bool zero)   //ok表示之前的位置已经用了哪些数字,flag表示是否有取值限制,zero表示是否有前导0
    17 {
    18     if(len==-1) return mp(1,0);
    19     if(!flag&&!zero&&dp[len][ok].first!=-1) return dp[len][ok];
    20     pair<ll,ll> ans=mp(0,0);
    21     int limit=flag?a[len]:9;
    22     for(int i=0;i<=limit;++i)
    23     {
    24         int mask=ok|(1<<i);
    25         if(i==0&&zero) mask=ok;
    26         if(__builtin_popcount(mask)>d) continue;
    27         pair<ll,ll> to=dfs(len-1,mask,flag&&i==a[len],zero&&i==0);
    28         update(ans.first,to.first);
    29         update(ans.second,to.second);
    30         update(ans.second,1LL*to.first*pw[len]%mod*i%mod);
    31     }
    32     if(!flag) dp[len][ok]=ans;
    33     return ans;
    34 }
    35 ll cal(ll n)
    36 {
    37     int len=-1;
    38     while(n)
    39     {
    40         a[++len]=n%10;
    41         n/=10;
    42     }
    43     for(int i=0;i<19;++i)
    44         for(int j=0;j<1024;++j)
    45             dp[i][j]=mp(-1,-1);
    46     return dfs(len,0,1,1).second;
    47 }
    48 int main()
    49 {
    50     pw[0]=1;
    51     for(int i=1;i<20;++i) pw[i]=pw[i-1]*10%mod;
    52     ll l,r;
    53     cin>>l>>r>>d;
    54     printf("%lld
    ",(cal(r)-cal(l-1)+mod)%mod);
    55     return 0;
    56 }
    View Code

    FastIO(不支持读负数、EOF)

     1 typedef long long LL;
     2 namespace fastIO {
     3     #define BUF_SIZE 100000
     4     //fread -> read
     5     bool IOerror = 0;
     6     inline char nc() {
     7         static char buf[BUF_SIZE], *p1 = buf + BUF_SIZE, *pend = buf + BUF_SIZE;
     8         if(p1 == pend) {
     9             p1 = buf;
    10             pend = buf + fread(buf, 1, BUF_SIZE, stdin);
    11             if(pend == p1) {
    12                 IOerror = 1;
    13                 return -1;
    14             }
    15         }
    16         return *p1++;
    17     }
    18     inline bool blank(char ch) {
    19         return ch == ' ' || ch == '
    ' || ch == '
    ' || ch == '	';
    20     }
    21     inline void read(int &x) {
    22         char ch;
    23         while(blank(ch = nc()));
    24         if(IOerror)
    25             return;
    26         for(x = ch - '0'; (ch = nc()) >= '0' && ch <= '9'; x = x * 10 + ch - '0');
    27     }
    28     #undef BUF_SIZE
    29 };
    30 using namespace fastIO;
    View Code

    __int128读入输出

     1 void scan(__int128 &x)//输入
     2 {
     3     x = 0;
     4     int f = 1;
     5     char ch;
     6     if((ch = getchar()) == ‘-‘) f = -f;
     7     else x = x*10 + ch-‘0‘;
     8     while((ch = getchar()) >= ‘0‘ && ch <= ‘9‘)
     9         x = x*10 + ch-‘0‘;
    10     x *= f;
    11 }
    12 void print(__int128 x)//输出
    13 {
    14     if(x < 0)
    15     {
    16         x = -x;
    17         putchar(‘-‘);
    18     }
    19      if(x > 9) print(x/10);
    20     putchar(x%10 + ‘0‘);
    21 }
    View Code

    单纯形法

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int maxn=500,maxm=500;
     4 const double eps=1e-8;
     5 int n,m,op,tot,q[maxn+5],idx[maxn+5],idy[maxm+5];
     6 double a[maxm+5][maxn+5];
     7 double x[maxn+5];
     8 void pivot(int x,int y)
     9 {
    10     swap(idy[x],idx[y]);
    11     double tmp = a[x][y]; a[x][y] = 1/a[x][y];
    12     for (int i = 0;i <= n;++i)
    13         if (y != i) a[x][i] /= tmp;
    14     tot = 0;
    15     for (int i = 0;i <= n;++i)
    16         if (i != y&&(a[x][i] > eps||a[x][i] < -eps)) q[++tot] = i;
    17     for (int i = 0;i <= m;++i)
    18     {
    19         if ((x == i)||(a[i][y] < eps&&a[i][y] > -eps)) continue;
    20         for (int j = 1;j <= tot;++j) a[i][q[j]] -= a[x][q[j]]*a[i][y];
    21         a[i][y] = -a[i][y]/tmp;
    22     }
    23 }
    24 int simplex(double &ans,double *x)
    25 {
    26     /*
    27     -1:无界
    28     0:无解
    29     1:有最优解
    30     有最优解时候答案放ans中,解放x[]中
    31     */
    32     for(int i = 1;i <= n;++i) idx[i] = i;
    33     for(int i = 1;i <= m;++i) idy[i] = i+n;
    34     while(true)
    35     {
    36         int x = 0,y = 0;
    37         for (int i = 1;i <= m;++i)
    38             if (a[i][0] < -eps&&((!x)||(rand()&1))) x = i;
    39         if (!x) break;
    40         for (int i = 1;i <= n;++i)
    41             if (a[x][i] < -eps&&((!y)||(rand()&1))) y = i;
    42         if (!y) return 0;
    43         pivot(x,y);
    44     }
    45     while (true)
    46     {
    47         int x = 0,y = 0; double mn = 1e15;
    48         for (int i = 1;i <= n;++i)
    49             if (a[0][i] > eps) { y = i; break; }
    50         if (!y) break;
    51         for (int i = 1;i <= m;++i)
    52             if (a[i][y] > eps && a[i][0]/a[i][y] < mn) mn = a[i][0]/a[i][y],x = i;
    53         if (!x) return -1;
    54         pivot(x,y);
    55     }
    56     ans=-a[0][0];
    57     for (int i = 1;i <= m;++i)
    58         if (idy[i] <= n) x[idy[i]] = a[i][0];
    59     return 1;
    60 }
    61 int main()
    62 {
    63     scanf("%d%d%d",&n,&m,&op);
    64     srand(233);
    65     for (int i = 1;i <= n;++i) scanf("%lf",&a[0][i]);   //第0行放目标函数的系数
    66     for (int i = 1;i <= m;++i)
    67     {
    68         for (int j = 1;j <= n;++j) scanf("%lf",&a[i][j]);
    69         scanf("%lf",&a[i][0]);                           //第0列放每个限制右边的上界
    70     }
    71     double ans;
    72     int tmp=simplex(ans,x);
    73     if(tmp==0) puts("Infeasible");
    74     else
    75         if(tmp==-1) puts("Unbounded");
    76         else
    77         {
    78             printf("%.9f
    ",ans);
    79             if(op==1) for(int i=1;i<=n;++i) printf("%.9f ",x[i]);
    80         }
    81     return 0;
    82 }
    View Code

    BigInt

      1 typedef long long LL;
      2 struct BigInt
      3 {
      4     static const int BASE = 100000000;      //基数
      5     static const int WIDTH = 32;             //基宽
      6     vector<int> s;                          //存储
      7 
      8     //构造函数 -- 使用LL
      9     BigInt(long long num = 0)
     10     {
     11         *this = num;
     12     }
     13 
     14     //赋值运算符 -- 使用LL
     15     BigInt operator = (long long num)
     16     {
     17         s.clear();
     18         do
     19         {
     20             s.push_back(num % BASE);
     21             num /= BASE;
     22         }
     23         while(num > 0);
     24         return *this;
     25     }
     26     //赋值运算符 -- 使用string
     27     BigInt operator = (const string& str)
     28     {
     29         s.clear();
     30         int x, len = (str.length() - 1) / WIDTH + 1;
     31         for(int i = 0; i < len; i++)
     32         {
     33             int end = str.length() - i*WIDTH;
     34             int start = max(0, end - WIDTH);
     35             sscanf(str.substr(start, end-start).c_str(), "%d", &x);
     36             s.push_back(x);
     37         }
     38         return *this;
     39     }
     40 
     41     //比较运算符
     42     bool operator < (const BigInt& b) const
     43     {
     44         if(s.size() != b.s.size()) return s.size() < b.s.size();
     45         for(int i = s.size()-1; i >= 0; i--)
     46             if(s[i] != b.s[i]) return s[i] < b.s[i];
     47         return false; //相等
     48     }
     49     bool operator >  (const BigInt& b) const
     50     {
     51         return b < *this;
     52     }
     53     bool operator <= (const BigInt& b) const
     54     {
     55         return !(b < *this);
     56     }
     57     bool operator >= (const BigInt& b) const
     58     {
     59         return !(*this < b);
     60     }
     61     bool operator != (const BigInt& b) const
     62     {
     63         return b < *this || *this < b;
     64     }
     65     bool operator == (const BigInt& b) const
     66     {
     67         return !(b < *this) && !(*this < b);
     68     }
     69 
     70     //重载输入输出
     71     friend ostream& operator << (ostream &out, const BigInt& x)
     72     {
     73         out << x.s.back();
     74         for(int i = x.s.size()-2; i >= 0; i--)
     75         {
     76             char buf[20];
     77             sprintf(buf, "%08d", x.s[i]);
     78             for(int j = 0; j < strlen(buf); j++) out << buf[j];
     79         }
     80         return out;
     81     }
     82     friend istream& operator >> (istream &in, BigInt& x)
     83     {
     84         string s;
     85         if(!(in >> s)) return in;
     86         x = s;
     87         return in;
     88     }
     89 
     90     //加法
     91     BigInt operator + (const BigInt& b) const
     92     {
     93         BigInt c;
     94         c.s.clear();
     95         for(int i = 0, g = 0; ; i++)
     96         {
     97             if(g == 0 && i >= s.size() && i >= b.s.size()) break;
     98             int x = g;
     99             if(i < s.size())    x += s[i];
    100             if(i < b.s.size())  x += b.s[i];
    101             c.s.push_back(x % BASE);
    102             g = x / BASE;
    103         }
    104         return c;
    105     }
    106 
    107     //加等于
    108     BigInt operator += (const BigInt& b)
    109     {
    110         *this = *this + b;
    111         return *this;
    112     }
    113 
    114 
    115 
    116 //减法 -- 大减小 -- 其他的在外部处理
    117     BigInt operator - (const BigInt& b) const
    118     {
    119         BigInt c;
    120         c.s.clear();
    121         if((*this) == b) return c = 0;
    122         for(int i = 0, g = 0; ; ++i)
    123         {
    124             if(g == 0 && i >= s.size() && i >= b.s.size()) break;
    125             int x = -g;
    126             g = 0;
    127             if(i < s.size())    x += s[i];
    128             if(i < b.s.size())  x -= b.s[i];
    129             if(x < 0) x += BASE, ++g;
    130             c.s.push_back(x);
    131         }
    132         for(int i = c.s.size()-1; i >= 0 && c.s[i] == 0; --i) c.s.pop_back();
    133         return c;
    134     }
    135 
    136 
    137     //乘法 -- 未使用FFT
    138     BigInt operator * (const BigInt& b) const
    139     {
    140         int s1 = s.size(), s2 = b.s.size();
    141         vector<LL> v(s1+s2+1,0);
    142         BigInt c;
    143         c.s.resize(s1+s2, 0);
    144         for(int i = 0; i < s1; ++i)        //相乘
    145             for(int j = 0; j < s2; ++j)
    146             {
    147                 v[i+j] += (LL)s[i]*b.s[j];
    148             }
    149         for(int i = 0; i < s1+s2; ++i)      //进位
    150         {
    151             v[i+1] += v[i]/BASE;
    152             v[i] %= BASE;
    153             c.s[i] = v[i];
    154         }
    155         for(int i = c.s.size()-1; i >= 0 && c.s[i] == 0; --i) c.s.pop_back();
    156         return c;
    157     }
    158 
    159     //除法 -- 二分
    160     BigInt operator / (const BigInt& b) const
    161     {
    162         int s1 = s.size(), s2 = b.s.size();
    163         int len = s1-s2;
    164         BigInt c, x = *this, y = b;
    165         if(len < 0) return c = 0;
    166 
    167         c.s.resize(len+1, 0);
    168         for(int i = len; i >= 0; --i)
    169         {
    170             //先将除数对齐
    171             y.s.resize(s2+i,0);
    172             for(int j = s2+i-1; j >= 0; --j)
    173             {
    174                 if(j >= i) y.s[j] = b.s[j-i];
    175                 else y.s[j] = 0;
    176             }
    177             //再二分找商
    178             int L = 0, R = BASE;
    179             BigInt t;
    180             while(L < R)
    181             {
    182                 int mid = (L+R)>>1;
    183                 t = mid;
    184                 if(t*y > x) R = mid;
    185                 else L = mid+1;
    186             }
    187             c.s[i] = L-1;
    188             //更新被除数
    189             t = L-1;
    190             x = x - t*y;
    191         }
    192         for(int i = c.s.size()-1; i >= 0 && c.s[i] == 0; --i) c.s.pop_back();
    193         return c;
    194     }
    195 
    196     //取模
    197     BigInt operator % (const BigInt& b) const
    198     {
    199         return (*this) - (*this)/b * b;
    200     }
    201 
    202     //开方 -- 二分 -- 浮点数可放大1e4精确一位
    203     BigInt Sqrt()
    204     {
    205         BigInt L = 1, R = *this;
    206         while(L < R)
    207         {
    208             BigInt mid = (L+R)/2;
    209             if(mid*mid > *this) R = mid;
    210             else L = mid+1;
    211         }
    212         return L-1;
    213     }
    214 };
    View Code

    Java大数类

     1 import java.math.BigDecimal;
     2 import java.math.BigInteger;
     3 import java.util.Scanner;
     4 
     5         Scanner cin=new Scanner(System.in);
     6 
     7         BigInteger num1=new BigInteger("12345");
     8         BigInteger num2=cin.nextBigInteger();
     9 
    10         BigDecimal num3=new BigDecimal("123.45");
    11         BigDecimal num4=cin.nextBigDecimal();
    12 
    13 //BigInteger
    14 public class Main {
    15     public static void main(String[] args) {
    16         BigInteger num1=new BigInteger("12345");
    17         BigInteger num2=new BigInteger("45");
    18         //加法
    19         System.out.println(num1.add(num2));
    20         //减法
    21         System.out.println(num1.subtract(num2));
    22         //乘法
    23         System.out.println(num1.multiply(num2));
    24         //除法(相除取整)
    25         System.out.println(num1.divide(num2));
    26         //取余
    27         System.out.println(num1.mod(num2));
    28         //最大公约数GCD
    29         System.out.println(num1.gcd(num2));
    30         //取绝对值
    31         System.out.println(num1.abs());
    32         //取反
    33         System.out.println(num1.negate());
    34         //取最大值
    35         System.out.println(num1.max(num2));
    36         //取最小值
    37         System.out.println(num1.min(num2));
    38         //是否相等
    39         System.out.println(num1.equals(num2));
    40     }
    41 }
    42 
    43 //BigDecimal
    44 public class Main {
    45     public static void main(String[] args) {
    46         BigDecimal num1=new BigDecimal("123.45");
    47         BigDecimal num2=new BigDecimal("4.5");
    48         //加法
    49         System.out.println(num1.add(num2));
    50         //减法
    51         System.out.println(num1.subtract(num2));
    52         //乘法
    53         System.out.println(num1.multiply(num2));
    54         //除法(在divide的时候就设置好要精确的小数位数和舍入模式)
    55         System.out.println(num1.divide(num2,10,BigDecimal.ROUND_HALF_DOWN));
    56         //取绝对值
    57         System.out.println(num1.abs());
    58         //取反
    59         System.out.println(num1.negate());
    60         //取最大值
    61         System.out.println(num1.max(num2));
    62         //取最小值
    63         System.out.println(num1.min(num2));
    64         //是否相等
    65         System.out.println(num1.equals(num2));
    66         //判断大小( > 返回1, < 返回-1)
    67         System.out.println(num2.compareTo(num1));
    68     }
    69 }
    View Code

    Montgomery乗算

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 #define rep(i,a,n) for (int i=a;i<n;i++)
     4 // head
     5 typedef unsigned long long u64;
     6 typedef long long ll;
     7 typedef __int128_t i128;
     8 typedef __uint128_t u128;
     9 int k;
    10 u64 A0,A1,M0,M1,C,M;
    11 
    12 struct Mod64 {
    13     Mod64():n_(0) {}
    14     Mod64(u64 n):n_(init(n)) {}
    15     static u64 init(u64 w) { return reduce(u128(w) * r2); }
    16     static void set_mod(u64 m) {
    17         mod=m; assert(mod&1);
    18         inv=m; rep(i,0,5) inv*=2-inv*m;
    19         r2=-u128(m)%m;
    20     }
    21     static u64 reduce(u128 x) {
    22         u64 y=u64(x>>64)-u64((u128(u64(x)*inv)*mod)>>64);
    23         return ll(y)<0?y+mod:y;
    24     }
    25     Mod64& operator += (Mod64 rhs) { n_+=rhs.n_-mod; if (ll(n_)<0) n_+=mod; return *this; }
    26     Mod64 operator + (Mod64 rhs) const { return Mod64(*this)+=rhs; }
    27     Mod64& operator -= (Mod64 rhs) { n_-=rhs.n_; if (ll(n_)<0) n_+=mod; return *this; }
    28     Mod64 operator - (Mod64 rhs) const { return Mod64(*this)-=rhs; }
    29     Mod64& operator *= (Mod64 rhs) { n_=reduce(u128(n_)*rhs.n_); return *this; }
    30     Mod64 operator * (Mod64 rhs) const { return Mod64(*this)*=rhs; }
    31     u64 get() const { return reduce(n_); }
    32     static u64 mod,inv,r2;
    33     u64 n_;
    34 };
    35 u64 Mod64::mod,Mod64::inv,Mod64::r2;
    36 int main() {
    37     int T;
    38     scanf("%d",&T);
    39     while(T--)
    40     {
    41         scanf("%llu%llu%llu%llu%llu%llu%d",&A0,&A1,&M0,&M1,&C,&M,&k);
    42         Mod64::set_mod(M);
    43         Mod64 a0(A0),a1(A1),m0(M0),m1(M1),c(C),ans(1),a2(0);
    44         for (int i=0;i<=k;i++) {
    45             ans=ans*a0;
    46             a2=m0*a1+m1*a0+c;
    47             a0=a1; a1=a2;
    48         }
    49         printf("%llu
    ",ans.get());
    50     }
    51 }
    View Code

     一维模拟退火

     1 /*
     2 F(x)=6*x^7+8*x^6+7*x^3+5*x^2-y*x (0 <= x <=100)
     3 求F(x)最小值
     4 */
     5 #include<bits/stdc++.h>
     6 using namespace std;
     7 const double EPS=1e-6;
     8 const double r=0.98;
     9 const int dx[2]={-1,1};
    10 double y;
    11 
    12 double F(double x)
    13 {
    14     return 6*pow(x,7)+8*pow(x,6)+7*pow(x,3)+5*pow(x,2)-y*x;
    15 }
    16 
    17 int main()
    18 {
    19     int T;
    20     cin>>T;
    21     while(T--)
    22     {
    23         cin>>y;
    24         double step=100;
    25         double x=0;
    26         while(step>EPS)
    27         {
    28             for(int i=0;i<2;i++)
    29             {
    30                 double next_x=x+dx[i]*step;
    31                 if(next_x<0||next_x>100)
    32                     continue;
    33                 if(F(next_x)<F(x))
    34                     x=next_x;
    35             }
    36             step*=r;
    37         }
    38         printf("%.4f
    ",F(x));
    39     }
    40     return 0;
    41 }
    View Code

    二维模拟退火

     1 /*
     2 给你一个搜索范围 ( 0,0 ) 到 ( X ,Y )这个矩形范围,给你N个点,
     3 要求找出一个点使这个点到这 N 个点的最大距离最小。
     4 可以想象的就是把一维转变成二维,那么单点搜索我们就可以变成随机多点并行搜索,
     5 原来的双向移动,转变为360度随机移动。最后在多点的搜索结果中取最优。
     6 显然移动是以圆的范围移动的,那么温度上界 T 取矩形对角线, 即圆的最大半径,
     7 精度为小数点后1位, 精确度EPS取1e-3, 降温速率 r 取0.8,对于每个点我随机了36次移动
     8 */
     9 #include<bits/stdc++.h>
    10 using namespace std;
    11 
    12 const double EPS=1e-3;
    13 const double PI=acos(-1.0);
    14 const double INF=0x3f3f3f3f;
    15 const double r=0.8;
    16 const int maxn=1e4+5;
    17 const int num=20;
    18 
    19 struct Point{
    20     double x,y;
    21 };
    22 
    23 Point a[maxn];
    24 Point m[maxn];
    25 int n;
    26 double d[maxn];
    27 
    28 double dist(Point A, Point B)
    29 {
    30     return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));
    31 }
    32 
    33 double MAX(Point t)
    34 {
    35     double res=-1;
    36     for(int i=0;i<n;i++)
    37         res=max(res,dist(t,a[i]));
    38     return res;
    39 }
    40 
    41 int main()
    42 {
    43     double xx,yy;
    44     srand(time(0));
    45     while(cin>>xx>>yy>>n)
    46     {
    47         for(int i=0;i<n;i++)
    48             cin>>a[i].x>>a[i].y;
    49         for(int i=0;i<num;i++)
    50         {
    51             m[i].x=(rand()%1000+1)/1000.0*xx;
    52             m[i].y=(rand()%1000+1)/1000.0*yy;
    53             d[i]=MAX(m[i]);
    54         }
    55         double T=sqrt(xx*xx+yy*yy);
    56         Point next,now;
    57         while(T>EPS)
    58         {
    59             for(int i=0;i<num; i++)
    60             {
    61                 now.x=m[i].x;
    62                 now.y=m[i].y;
    63                 for(int j=0;j<36;j++)
    64                 {
    65                     double ang=(rand()%1000+1)/1000.0*2*PI;
    66                     next.x=now.x+cos(ang)*T;
    67                     next.y=now.y+sin(ang)*T;
    68                     if(next.x<0||next.x>xx||next.y<0||next.y>yy)
    69                         continue;
    70                     if(MAX(next)<d[i])
    71                     {
    72                         m[i].x=next.x;
    73                         m[i].y=next.y;
    74                         d[i]=MAX(next);
    75                     }
    76                 }
    77             }
    78             T*=r;
    79         }
    80         int res;
    81         double ans=INF;
    82         for(int i=0;i<num;i++)
    83         {
    84             if(d[i]<ans)
    85             {
    86                 ans=d[i];
    87                 res=i;
    88             }
    89         }
    90         printf("(%.1f,%.1f).
    ",m[res].x,m[res].y);
    91         printf("%.1f
    ",ans);
    92     }
    93     return 0;
    94 }
    View Code

     

    更新日志:

    2018.9.19 创建版本1.0.0

    2018.9.25 更新SAM模板拓扑排序部分(同时支持自动机和parent树的拓扑序)

    2018.9.25 更新杜教筛写法,实现了O(1)记忆化(鸣谢Feynman1999)

    2018.10.9 加入“最小费用最大流(dijkstrar实现)”,这个费用流板子跑得飞快

    2018.10.10 更新单纯形模板

    2018.10.12 加入“min25筛”模板

    2018.10.19 加入“KM算法”模板

    2018.10.23 更新了“类欧几里得”模板

    2018.10.25 加入“Montgomery乗算”模板

    2018.10.26 更新了“数位DP”模板

    2018.11.23 加入了“一维模拟退火”模板

    2018.11.23 加入了“二维模拟退火”模板

  • 相关阅读:
    递归--练习5--noi1751分解因数
    递归--练习4--noi666放苹果
    递归--练习3--noi7592求最大公约数问题
    递归--练习2--noi6261汉诺塔
    递归--练习1--noi3089爬楼梯
    JavaScript--语法4--函数1
    JavaScript--语法3--数组
    JavaScript--练习1--99乘法表
    应用排行榜第一名脸萌仅仅是刹那的烟火
    Readprocessmemory使用方法
  • 原文地址:https://www.cnblogs.com/Amadeus/p/9675081.html
Copyright © 2011-2022 走看看