zoukankan      html  css  js  c++  java
  • NOIP常见模板集合

    Preface

    这篇博客记录的是我联赛前虽然只有两天了的打板子记录。

    只求真的能给我起到些作用吧,一般按照难度排序。

    而且从这篇博客开始我会用H3的标题代替H4

    为了节约篇幅,以下的代码一般均以class的形式给出,模板题均来自Luogu


    快读快输(文件操作)

    这是基础中的基础吧,这个感觉敲出来还是没什么问题的(默认不读/输负数)

    class FileInputOutput
    {
    	private:
    		#define S 1<<21
    		#define tc() (A==B&&(B=(A=Fin)+fread(Fin,1,S,stdin),A==B)?EOF:*A++)
    		#define pc(ch) (Ftop<S?Fout[Ftop++]=ch:(fwrite(Fout,1,S,stdout),Fout[(Ftop=0)++]=ch))
    		char Fin[S],Fout[S],*A,*B; int pt[15],Ftop;
    	public:
    		FileInputOutput() { A=B=Fin; Ftop=0; }
    		inline void read(int &x)
    		{
    			x=0; char ch; while (!isdigit(ch=tc()));
    			while (x=(x<<3)+(x<<1)+(ch&15),isdigit(ch=tc()));
    		}
    		inline void write(int x,char ch)
    		{
    			if (!x) return (void)(pc('0'),pc(ch)); RI ptop=0;
    			while (x) pt[++ptop]=x%10,x/=10; while (ptop) pc(pt[ptop--]+48); pc(ch);
    		}
    		inline void Fend(void)
    		{
    			fwrite(Fout,1,Ftop,stdout);
    		}
    		#undef S
    		#undef tc
    		#undef pc
    }F;
    

    P1177 【模板】快速排序

    快排模板?调用sort也太没技术含量了吧?

    写一发松式基排,感觉速率还可以吧,一次过这个一次过不了退役算了

    class Radix_Sort
    {
    	private:
    		int cnt1[Radix+1],cnt2[Radix+1],cnt3[Radix+1],cnt4[Radix+1]; u32 b[N];
    	public:
    		inline void sort(u32 *a,int n)
    		{
    			RI i; for (i=1;i<=n;++i)
    			{
    				++cnt1[a[i]&Radix]; ++cnt2[a[i]>>8&Radix];
    				++cnt3[a[i]>>16&Radix]; ++cnt4[a[i]>>24&Radix];
    			}
    			for (i=1;i<=Radix;++i)
    			{
    				cnt1[i]+=cnt1[i-1]; cnt2[i]+=cnt2[i-1];
    				cnt3[i]+=cnt3[i-1]; cnt4[i]+=cnt4[i-1];
    			}
    			for (i=n;i;--i) b[cnt1[a[i]&Radix]--]=a[i];
    			for (i=n;i;--i) a[cnt2[b[i]>>8&Radix]--]=b[i];
    			for (i=n;i;--i) b[cnt3[a[i]>>16&Radix]--]=a[i];
    h+++++++			for (i=n;i;--i) a[cnt4[b[i]>>24&Radix]--]=b[i];
    		}
    }R;
    

    l


    P3367 【模板】并查集

    写了个按秩合并,然后getfather忘记returnMLE了一大片

    class FindUnionSet
    {
        private:
            int father[N],size[N];
            inline void swap(int &x,int &y)
            {
                int t=x; x=y; y=t;
            }
            inline int getfather(int x)
            {
                return father[x]^x?father[x]=getfather(father[x]):x;
            }
        public:
            inline void init(void)
            {
                for (RI i=1;i<=n;++i) father[i]=i,size[i]=1;
            }
            inline bool Identify(int x,int y)
            {
                return getfather(x)==getfather(y);
            }
            inline void Union(int x,int y)
            {
                x=getfather(x); y=getfather(y);
                if (x==y) return; if (size[x]<size[y]) swap(x,y);
                father[y]=x; size[x]+=size[x]==size[y]; size[y]=0;
            }
    }S;
    

    P1226 【模板】快速幂||取余运算

    快速幂板子题居然WA了两发,注意要特判模数为(0)的情况。

    inline int quick_pow(int x,int p,int mod,int mul=1)
    {
    	if (mod==1) return 0;
        for (;p;p>>=1,x=1LL*x*x%mod) if (p&1) mul=1LL*mul*x%mod; return mul;
    }
    

    P3383 【模板】线性筛素数

    不想写MR,还是写个欧拉筛即可。

    #define Pi prime[j]
    inline void Euler(int n)
    {
        vis[1]=1; for (RI i=2;i<=n;++i)
        {
            if (!vis[i]) prime[++cnt]=i;
            for (RI j=1;j<=cnt&&i*Pi<=n;++j)
            {
                vis[i*Pi]=1; if (i%Pi==0) break;
            }
        }
    }
    #undef Pi
    

    P3378 【模板】堆

    懒得写堆了因为我不会,又不想左偏树,直接STL好了。


    P3370 【模板】字符串哈希

    写了发挂链Hash,不过速度有点慢,说实话不如用map

    class Hasher_Solver
    {
        private:
            #define P 2333333
            struct Hasher
            {
                int nxt; string val;
            }link[10005]; int head[P],cnt;
            inline int Hash(string s)
            {
                int len=s.size(),ret=0; for (RI i=0;i<len;++i)
                ret=((ret<<3)+(ret<<1)+s[i])%P; return ret;
            }
        public:
            inline bool find(string s)
            {
                int now=Hash(s); bool is_exist=0;
                for (RI i=head[now];i;i=link[i].nxt)
                if (link[i].val==s) { is_exist=1; break; }
                return is_exist;
            }
            inline void insert(string s)
            {
                int now=Hash(s); link[++cnt]=(Hasher){head[now],s}; head[now]=cnt;
            }
    }H;
    

    P3366 【模板】最小生成树

    一般推荐写Kruskal,并查集参照上面。

    class MST_Kruskal
    {
        private:
            int cur; long long ans;
        public:
            inline void Kruskal(void)
            {
                RI i; for (sort(a+1,a+m+1),S.init(),i=1;i<=m;++i)
                if (!S.Identify(a[i].l,a[i].r)) S.Union(a[i].l,a[i].r),ans+=a[i].val,++cur;
                if (cur!=n-1) puts("orz"); else printf("%lld",ans);
            }
    }K;
    

    Prim也写一发吧,虽然并没有什么卵用

    class MST_Prim
    {
    	private:
    		struct data
    		{
    			int id,val;
    			data(int Id=0,int Val=0) { id=Id; val=Val; }
    			inline friend bool operator <(data a,data b)
    			{
    				return a.val>b.val;
    			}
    		}; priority_queue <data> small; long long ans; int cur,dis[N]; bool vis[N];
    	public:
    		#define to e[i].to
    		inline void Prim(void)
    		{
    			memset(dis,63,sizeof(dis)); small.push(data(1,dis[1]=0));
    			while (!small.empty())
    			{
    				int now=small.top().id; small.pop(); if (vis[now]) continue;
    				++cur; ans+=dis[now]; vis[now]=1; for (RI i=head[now];i;i=e[i].nxt)
    				if (dis[to]>e[i].v) small.push(data(to,dis[to]=e[i].v));
    			}
    			if (cur!=n) puts("orz"); else printf("%lld",ans);
    		}
    		#undef to
    }P;
    

    P3371 【模板】单源最短路径(弱化版)

    这个练习一下SPFA好了虽然它已经死了,标准版再写DJ

    class SLF_SPFA
    {
        private:
            deque <int> q; int dis[N]; bool vis[N];
        public:
            #define to e[i].to
            inline void SPFA(int s)
            {
                RI i; for (RI i=1;i<=n;++i) dis[i]=INF; vis[s]=1; dis[s]=0; q.push_front(s);
                while (!q.empty())
                {
                    int now=q.front(); q.pop_front(); vis[now]=0;
                    for (i=head[now];i;i=e[i].nxt) if (dis[to]>dis[now]+e[i].v)
                    {
                        dis[to]=dis[now]+e[i].v; if (!vis[to])
                        {
                            if (q.empty()||dis[q.front()]>dis[to])
                            q.push_front(to); else q.push_back(to); vis[to]=1;
                        }
                    }
                }
            }
            #undef to
            inline void print(void)
            {
                for (RI i=1;i<=n;++i) F.write(dis[i]);
            }
    }S;
    

    P3374 【模板】树状数组 1

    手速码树状数组,不要像某九条可怜一样就好。

    class BIT
    {
        private:
            long long bit[N];
            #define lowbit(x) x&-x
        public:
            inline void add(RI x,int y)
            {
                for (;x<=n;x+=lowbit(x)) bit[x]+=y;
            }
            inline long long get(RI x,long long ret=0)
            {
                for (;x;x-=lowbit(x)) ret+=bit[x]; return ret;
            }
            #undef lowbit
    }T;
    

    P3368 【模板】树状数组 2

    类似于模板1,再之前的基础上查分一下就好了。核心部分:

    F.read(opt),F.read(x),(opt^2?F.read(y),F.read(z),T.add(x,z),T.add(y+1,-z):F.write(T.get(x)));
    

    P3382 【模板】三分法

    按题意搞就好了,函数的计算可以套一个秦九昭算法

    inline DB F(DB x)
    {
        DB ret=0; for (RI i=n;~i;--i)
        ret=ret*x+a[n-i]; return ret;
    }
    DB lmid,rmid; while (r-l>EPS)
    {
        lmid=l+(r-l)/3.0; rmid=r-(r-l)/3.0;
        if (F(lmid)-F(rmid)<-EPS) l=lmid; else r=rmid;
    }
    

    P3865 【模板】ST表

    简单的RMQ不做多解释

    class RMQ_Solver
    {
        private:
            #define P 18
            int log[N],f[N][P];
            inline int max(int a,int b)
            {
                return a>b?a:b;
            }
            inline void swap(int &a,int &b)
            {
                int t=a; a=b; b=t;
            }
        public:
            inline void log_init(void)
            {
                for (RI i=2;i<=n;++i) log[i]=log[i>>1]+1;
            }
            inline void RMQ_init(void)
            {
                RI i; for (i=1;i<=n;++i) f[i][0]=a[i];
                for (RI j=1;j<P;++j) for (i=1;i+(1<<j)-1<=n;++i)
                f[i][j]=max(f[i][j-1],f[i+(1<<j-1)][j-1]);
            }
            inline int query(int l,int r)
            {
                if (l>r) swap(l,r); int t=log[r-l+1];
                return max(f[l][t],f[r-(1<<t)+1][t]);
            }
            #undef P
    }R;
    

    P3390 【模板】矩阵快速幂

    矩阵板子,习惯封装成结构体。

    struct Matrix
    {
        int n,a[N][N];
        Matrix(int N=0) { n=N; memset(a,0,sizeof(a)); }
        inline void input(void)
        {
            for (RI i=1;i<=n;++i) for (RI j=1;j<=n;++j) F.read(a[i][j]);
        }
        inline void output(void)
        {
            for (RI i=1;i<=n;++i) for (RI j=1;j<=n;++j) F.write(a[i][j],j^n?' ':'
    ');
        }
        inline void Cri_init(void)
        {
            for (RI i=1;i<=n;++i) a[i][i]=1;
        }
    }; int n; long long k;
    inline Matrix operator *(Matrix A,Matrix B)
    {
        Matrix C(n); for (RI i=1;i<=n;++i)
        for (RI j=1;j<=n;++j) for (RI k=1;k<=n;++k)
        inc(C.a[i][j],1LL*A.a[i][k]*B.a[k][j]%mod);
        return C;
    }
    inline Matrix operator ^(Matrix A,long long p)
    {
        Matrix T(n); T.Cri_init(); for (;p;p>>=1,A=A*A)
        if (p&1) T=T*A; return T;
    }
    

    P3375 【模板】KMP字符串匹配

    KMP我除了板子什么都不会。。。

    class KMQ_Solver
    {
        private:
            int nxt[N],ans;
        public:
            inline void Get_nxt(void)
            {
                int len=0; for (RI i=2;i<=m;++i)
                {
                    while (len&&s2[len+1]!=s2[i]) len=nxt[len];
                    if (s2[len+1]==s2[i]) ++len; nxt[i]=len;
                }
            }
            inline void KMP(void)
            {
                int len=0; for (RI i=1;i<=n;++i)
                {
                    while (len&&s2[len+1]!=s1[i]) len=nxt[len];
                    if (s2[len+1]==s1[i]) ++len;
                    if (len==m) printf("%d
    ",i-len+1),len=nxt[len];
                }
            }
            inline void print(void)
            {
                for (RI i=1;i<=m;++i) printf("%d ",nxt[i]);
            }
    }K;
    

    P3811 【模板】乘法逆元

    据说这题逆元板子卡快速幂exgcd,只能写线性求逆元

    inline void Get_inv(int n)
    {
    	RI i; inv[1]=1; for (i=2;i<=n;++i)
    	inv[i]=(-1LL*inv[p%i]*(p/i)%p+p)%p;
    }
    

    P3372 【模板】线段树 1

    大力敲板子就好了,不要忘记清空标记。

    class FileInputOutput
    {
    	private:
    		#define S 1<<21
    		#define tc() (A==B&&(B=(A=Fin)+fread(Fin,1,S,stdin),A==B)?EOF:*A++)
    		#define pc(ch) (Ftop<S?Fout[Ftop++]=ch:(fwrite(Fout,1,S,stdout),Fout[(Ftop=0)++]=ch))
    		char Fin[S],Fout[S],*A,*B; int pt[25],Ftop;
    	public:
    		FileInputOutput() { A=B=Fin; Ftop=0; }
    		inline void read(int &x)
    		{
    			x=0; char ch; int flag=1; while (!isdigit(ch=tc())) flag=ch^'-'?1:-1;
    			while (x=(x<<3)+(x<<1)+(ch&15),isdigit(ch=tc())); x*=flag;
    		}
    		inline void write(LL x)
    		{
    			if (!x) return (void)(pc('0'),pc('
    ')); if (x<0) x=-x,pc('-'); RI ptop=0;
    			while (x) pt[++ptop]=x%10,x/=10; while (ptop) pc(pt[ptop--]+48); pc('
    ');
    		}
    		inline void Fend(void)
    		{
    			fwrite(Fout,1,Ftop,stdout);
    		}
    		#undef S
    		#undef tc
    		#undef pc
    }F;
    class Segment_Tree
    {
    	private:
    		struct Segment
    		{
    			LL sum,tag;
    		}node[N<<2];
    		#define pushup(x) node[x].sum=node[x<<1].sum+node[x<<1|1].sum
    		inline void pushdown(int now,int ltot,int rtot)
    		{
    			if (!node[now].tag) return; int val=node[now].tag;
    			node[now<<1].tag+=val; node[now<<1].sum+=1LL*ltot*val;
    			node[now<<1|1].tag+=val; node[now<<1|1].sum+=1LL*rtot*val;
    			node[now].tag=0;
    		}
    	public:
    		inline void build(int now,int l,int r)
    		{
    			if (l==r) return (void)(node[now].sum=a[l]); int mid=l+r>>1;
    			build(now<<1,l,mid); build(now<<1|1,mid+1,r); pushup(now);
    		}
    		#define O beg,end
    		inline void modify(int now,int l,int r,int beg,int end,int val)
    		{
    			if (l>=beg&&r<=end) return (void)(node[now].tag+=val,node[now].sum+=1LL*(r-l+1)*val);
    			int mid=l+r>>1; pushdown(now,mid-l+1,r-mid); if (beg<=mid) modify(now<<1,l,mid,O,val);
    			if (end>mid) modify(now<<1|1,mid+1,r,O,val); pushup(now);
    		}
    		inline LL query(int now,int l,int r,int beg,int end)
    		{
    			if (l>=beg&&r<=end) return node[now].sum; int mid=l+r>>1; pushdown(now,mid-l+1,r-mid);
    			LL ret=0; if (beg<=mid) ret+=query(now<<1,l,mid,O); if (end>mid) ret+=query(now<<1|1,mid+1,r,O); return ret;
    		}
    		#undef O
    		#undef pushup
    }T;
    

    P1939 【模板】矩阵加速(数列)

    手玩一下递推式就好了,矩阵快速幂参考上面。构造代码:

    inline void Cri_init(void)
    {
    	for (RI i=1;i<=n;++i) a[i][i]=1;
    }
    inline void Base_init(void)
    {
    	a[1][1]=a[2][1]=a[3][1]=1;
    }
    inline void DT_init(void)
    {
    	a[1][2]=a[2][3]=a[3][1]=a[3][3]=1;
    }
    

    P3379 【模板】最近公共祖先(LCA)

    写发最常用的倍增把,RMQ没什么用,Tarjan太烦还要离线。树剖的话。。。板子题再写吧。

    class LCA_DoubleIncreased
    {
        private:
            #define P 20
            int dep[N],father[N][P];
            inline void swap(int &a,int &b)
            {
                int t=a; a=b; b=t;
            }
            inline void reset(int now)
            {
                for (RI i=0;i<P-1;++i) if (father[now][i])
                father[now][i+1]=father[father[now][i]][i]; else break;
            }
        public:
            #define to e[i].to
            inline void DFS(int now,int fa)
            {
                dep[now]=dep[fa]+1; reset(now);
                for (RI i=head[now];i;i=e[i].nxt)
                if (to!=fa) father[to][0]=now,DFS(to,now);
            }
            #undef to
            inline int LCA(int x,int y)
            {
                if (dep[x]<dep[y]) swap(x,y); RI i;
                for (i=P-1;~i;--i) if (dep[father[x][i]]>=dep[y])
                x=father[x][i]; if (x==y) return x;
                for (i=P-1;~i;--i) if (father[x][i]!=father[y][i])
                x=father[x][i],y=father[y][i]; return father[x][0];
            }
    }T;
    

    P4779 【模板】单源最短路径(标准版)

    写了DJ,不想写堆然后就写了线段树优化当然没有写zkw线段树

    class Segment_Tree
    {
    	private:
    		struct Segment
    		{
    			int mi,id;
    			Segment(int Mi=INF,int Id=0) { mi=Mi; id=Id; }
    		}node[N<<2];
    		#define pushup(now) node[now]=node[now<<1].mi<node[now<<1|1].mi?node[now<<1]:node[now<<1|1];
    	public:
    		inline void modify(int now,int l,int r,int id,int val)
    		{
    			if (l==r) return (void)(node[now].mi=val,node[now].id=l);
    			int mid=l+r>>1; if (id<=mid) modify(now<<1,l,mid,id,val);
    			else modify(now<<1|1,mid+1,r,id,val); pushup(now);
    		}
    		inline int query(void)
    		{
    			return node[1].id;
    		}
    		inline bool empty(void)
    		{
    			return node[1].mi==INF;
    		}
    		#undef pushup
    }T;
    class Dijkstra_Solver
    {
    	private:
    		int dis[N];
    	public:
    		#define to e[i].to
    		inline void Dijkstra(int s)
    		{
    			RI i; for (i=1;i<=n;++i) dis[i]=INF; T.modify(1,1,n,s,dis[s]=0);
    			while (!T.empty())
    			{
    				int now=T.query(); T.modify(1,1,n,now,INF);
    				for (RI i=head[now];i;i=e[i].nxt) if (dis[to]>dis[now]+e[i].v)
    				T.modify(1,1,n,to,dis[to]=dis[now]+e[i].v);
    			}
    		}
    		#undef to
    		inline void print(void)
    		{
    			for (RI i=1;i<=n;++i) F.write(dis[i]);
    		}
    }D;
    

    P3807 【模板】卢卡斯定理

    这个板子太弱了吧,虽然直接暴力也能过。卢卡斯定理(C_n^moperatorname{mod}p=C_{lfloorfrac{n}{p} floor}^{lfloorfrac{m}{p} floor}cdot C_{noperatorname{mod}p}^{moperatorname{mod}p})

    inline void init(void)
    {
        RI i; for (fact[0]=i=1;i<p;++i) fact[i]=1LL*fact[i-1]*i%p;
        for (inv[p-1]=quick_pow(fact[p-1],p-2),i=p-2;~i;--i) inv[i]=1LL*inv[i+1]*(i+1)%p;
    }
    inline int C(int n,int m)
    {
        if (n<m) return 0; if (!n) return 1;
        return 1LL*fact[n]*inv[m]%p*inv[n-m]%p;
    }
    inline int Lucas(int n,int m)
    {
        if (n<m) return 0; if (!n) return 1;
        return 1LL*Lucas(n/p,m/p)*C(n%p,m%p)%p;
    }
    

    P1439 【模板】最长公共子序列

    因为这个是排列,所以我们可以离散化一下(A)中每个数在(B)中出现的位置,然后就是一个LIS了,直接二分维护单调性即可。

    class LIS
    {
        private:
            int r[N],stack[N],top;
            inline int find(int x)
            {
                int l=1,r=top-1,res=-1,mid; while (l<=r)
                if (stack[mid=l+r>>1]<x) res=mid,l=mid+1; else r=mid-1;
                return res;
            }
        public:
            inline void init(void)
            {
                RI i; for (i=1;i<=n;++i) r[a[i]]=i;
                for (i=1;i<=n;++i) b[i]=r[b[i]];
            }
            inline void solve(void)
            {
                stack[top=1]=b[1]; for (RI i=2;i<=n;++i)
                {
                    if (b[i]<stack[1]) stack[1]=b[i];
                    if (b[i]>stack[top]) stack[++top]=b[i];
                    else stack[find(b[i])+1]=b[i];
                }
                printf("%d",top);
            }
    }L;
    

    P2197 【模板】nim游戏

    这个结论吧,具体证明好像我也不会呵。

    RI i; for (ret=0,F.read(n),i=1;i<=n;++i)
    F.read(x),ret^=x; puts(ret?"Yes":"No");
    

    P3386 【模板】二分图匹配

    挺简短的匈牙利算法Dinic网络流的时候再写。

    class Brinary_Graph_Matching
    {
        private:
            int from[N],t[N];
        public:
            #define to e[i].to
            inline bool find(int now,int idx)
            {
                for (RI i=head[now];i;i=e[i].nxt)
                {
                    if (t[to]==idx) continue; t[to]=idx;
                    if (!from[to]||find(from[to],idx)) return from[to]=now,1;
                } return 0;
            }
            #undef to
    }M;
    

    P2613 【模板】有理数取余

    这TM就一SB题,一遍读入一边取模就好了,别忘了判无解!读入部分:

    inline void read(int &x)
    {
        x=0; char ch; while (!isdigit(ch=tc()));
        while (x=((x<<3)+(x<<1)+(ch&15))%mod,isdigit(ch=tc()));
    }
    

    P3805 【模板】manacher算法

    我为数不多会的字符串算法其实不会,板子挺好写的。

    class Manacher_Solver
    {
        private:
            char ns[N<<1]; int r[N<<1],n,pos,mx,ans;
            inline int min(int a,int b)
            {
                return a<b?a:b;
            }
            inline int max(int a,int b)
            {
                return a>b?a:b;
            }
        public:
            inline void change(void)
            {
                ns[0]='$'; ns[n=1]='%'; for (RI i=1;i<=len;++i) ns[++n]=s[i],ns[++n]='%';
            }
            inline void Manacher(void)
            {
                for (RI i=1;i<=n;++i)
                {
                    if (i<mx) r[i]=min(r[(pos<<1)-i],mx-i); else r[i]=1;
                    while (ns[i-r[i]]==ns[i+r[i]]) ++r[i];
                    if (i+r[i]>mx) mx=i+r[i],pos=i; ans=max(ans,r[i]);
                }
                printf("%d",ans-1);
            }
    }M;
    

    P3389 【模板】高斯消元法

    刚开始把高斯消元写成了行列式消元。。。然后又忘写负号了然后卡了很久才过样例。

    inline void swapline(int x)
    {
        RI now=x+1; while (fabs(a[now][x])<EPS&&now<=n) ++now;
        if (now>n) { puts("No Solution"); exit(0); }
        swap(a[x],a[now]); swap(val[x],val[now]);
    }
    inline void check(void)
    {
        for (RI i=1;i<=n;++i)
        {
            bool flag=0; for (RI j=1;j<=n;++j) flag|=fabs(a[i][j])>=EPS;
            if (!flag) { puts("No Solution"); exit(0); }
        }
    }
    inline void Gauss(void)
    {
        RI i,j; for (i=1;i<n;++i)
        {
            if (fabs(a[i][i])<EPS) swapline(i);
            for (RI j=i+1;j<=n;++j)
            {
                if (fabs(a[j][i])<EPS) continue;
                double d=-a[j][i]/a[i][i]; a[j][i]=0;
                for (RI k=i+1;k<=n;++k) a[j][k]+=d*a[i][k];
                val[j]+=d*val[i];
            }
        }
        for (check(),val[n]/=a[n][n],i=n-1;i;--i)
        {
            double ret=0; for (j=i+1;j<=n;++j) ret+=a[i][j]*val[j];
            val[i]=(val[i]-ret)/a[i][i];
        }
    }
    

    P3388 【模板】割点(割顶)

    交的时候Luogu上有个SB在卡评测据说交了2000多发

    class Cutting_Point_Solver
    {
        private:
            int dfn[N],low[N],idx,tot; bool cut[N];
            inline void miner(int &x,int y)
            {
                if (y<x) x=y;
            }
            #define to e[i].to
            inline void Tarjan(int now,int fa)
            {
                dfn[now]=low[now]=++idx; int son=0;
                for (RI i=head[now];i;i=e[i].nxt)
                if (!dfn[to])
                {
                    Tarjan(to,now); miner(low[now],low[to]); ++son;
                    if (fa&&low[to]>=dfn[now]) !cut[now]&&(cut[now]=1,++tot);
                } else if (to!=fa) miner(low[now],dfn[to]);
                if (!fa&&son>=2) !cut[now]&&(cut[now]=1,++tot);
            }
            #undef to
        public:
            inline void solve(void)
            {
                RI i; for (i=1;i<=n;++i) if (!dfn[i]) Tarjan(i,0);
                for (F.write(tot,'
    '),i=1;i<=n;++i) if (cut[i]) F.write(i,' ');
            }
    }T;
    

    P3385 【模板】负环

    好好写个板子都要卡我,据说判负环不能用SLF优化?去了就A了。

    #include<cstdio>
    #include<cstring>
    #include<queue>
    #define RI register int
    #define add(x,y,z) e[++cnt]=(edge){y,head[x],z},head[x]=cnt
    #define Ms(f,x) memset(f,x,sizeof(f))
    using namespace std;
    const int N=2005,M=3005;
    struct edge
    {
        int to,nxt,v;
    }e[M<<1]; queue <int> q; int t,m,head[N],n,cnt,x,y,z; bool vis[N];
    class Minus_Circle_Solver
    {
        private:
            int dis[N],tim[N]; bool vis[N];
        public:
            #define to e[i].to
            inline bool SPFA(void)
            {
                while (!q.empty()) q.pop(); Ms(dis,63); Ms(vis,0); Ms(tim,0);
                dis[1]=0; q.push(1); vis[1]=1;
                while (!q.empty())
                {
                    int now=q.front(); q.pop(); vis[now]=0;
                    if (++tim[now]>=n) return 1; for (RI i=head[now];i;i=e[i].nxt)
                    if (dis[to]>dis[now]+e[i].v)
                    {
                        dis[to]=dis[now]+e[i].v; if (!vis[to])
                        q.push(to),vis[to]=1;
                    }
                }
                return 0;
            }
            #undef to
    }C;
    int main()
    {
        for (scanf("%d",&t);t;--t)
        {
            RI i; for (scanf("%d%d",&n,&m),i=1;i<=m;++i)
            scanf("%d%d%d",&x,&y,&z),add(x,y,z),z>=0?add(y,x,z):0;
            puts(C.SPFA()?"YE5":"N0"); for (cnt=0,i=1;i<=n;++i) head[i]=0;
        }
        return 0;
    }
    

    P1919 【模板】A*B Problem升级版(FFT快速傅里叶)

    Python题,死也不写高精。NOIP应该不考吧

    input()
    a=int(input())
    b=int(input())
    print(a*b)
    

    P3387 【模板】缩点

    Tarjan缩一下点之后在DAG上用拓扑排序DP即可,练习到了挺多板子。1A真开心

    class Graph_Solver
    {
        private:
            edge ne[M]; int nhead[N],dfn[N],deg[N],low[N],idx,tot,col[N],stack[N],top,q[N],s[N],f[N]; bool vis[N];
            inline void miner(int &x,int y)
            {
                if (y<x) x=y;
            }
            inline void maxer(int &x,int y)
            {
                if (y>x) x=y;
            }
            #define nadd(x,y) ne[++cnt]=(edge){y,nhead[x]},nhead[x]=cnt,++deg[y]
            #define to ne[i].to
            inline void Top_sort(void)
            {
                RI i,H=0,T=0; for (i=1;i<=tot;++i) if (!deg[i]) q[++T]=i,f[i]=s[i];
                while (H<T)
                {
                    int now=q[++H]; for (i=nhead[now];i;i=ne[i].nxt)
                    {
                        maxer(f[to],f[now]+s[to]); maxer(ans,f[to]);
                        if (!(--deg[to])) q[++T]=to;
                    }
                }
            }
            #undef to
            #define to e[i].to
            inline void Tarjan(int now)
            {
                dfn[now]=low[now]=++idx; stack[++top]=now;
                vis[now]=1; for (RI i=head[now];i;i=e[i].nxt)
                if (!dfn[to]) Tarjan(to),miner(low[now],low[to]);
                else if (vis[to]) miner(low[now],dfn[to]);
                if (low[now]==dfn[now])
                {
                    col[now]=++tot; s[tot]=a[now]; vis[now]=0;
                    while (stack[top]!=now)
                    {
                        col[stack[top]]=tot; s[tot]+=a[stack[top]];
                        vis[stack[top--]]=0;
                    } --top; maxer(ans,s[tot]);
                }
            }
        public:
            inline void solve(void)
            {
                RI i,j; for (i=1;i<=n;++i) if (!dfn[i]) Tarjan(i);
                for (cnt=0,j=1;j<=n;++j) for (i=head[j];i;i=e[i].nxt)
                if (col[j]!=col[to]) nadd(col[j],col[to]); Top_sort();
            }
            #undef to
            #undef nadd
    }G;
    

    P3373 【模板】线段树 2

    维护一个乘法一个加法即可,注意先传乘法。刚开始pushup没取模跪了一发。

    class Segment_Tree
    {
        private:
            struct Segment
            {
                int sum,tag_mul,tag_add;
                Segment(int Sum=0,int Tag_mul=1,int Tag_add=0)
                {
                    sum=Sum; tag_mul=Tag_mul; tag_add=Tag_add;
                }
            }node[N<<2];
            inline void inc(int &x,int y)
            {
                if ((x+=y)>=mod) x-=mod;
            }
            #define pushup(x) node[x].sum=node[x<<1].sum,inc(node[x].sum,node[x<<1|1].sum)
            inline void pushdown(int now,int ltot,int rtot)
            {
                if (node[now].tag_mul!=1||node[now].tag_add)
                {
                    int lc=now<<1,rc=now<<1|1,mt=node[now].tag_mul,at=node[now].tag_add;
                    node[lc].tag_mul=1LL*node[lc].tag_mul*mt%mod;
                    node[lc].tag_add=1LL*node[lc].tag_add*mt%mod;
                    node[lc].sum=1LL*node[lc].sum*mt%mod;
                    inc(node[lc].tag_add,at); inc(node[lc].sum,1LL*ltot*at%mod);
                    node[rc].tag_mul=1LL*node[rc].tag_mul*mt%mod;
                    node[rc].tag_add=1LL*node[rc].tag_add*mt%mod;
                    node[rc].sum=1LL*node[rc].sum*mt%mod;
                    inc(node[rc].tag_add,at); inc(node[rc].sum,1LL*rtot*at%mod);
                    node[now].tag_mul=1; node[now].tag_add=0;
                }
            }
        public:
            inline void build(int now,int l,int r)
            {
                if (l==r) return (void)(node[now].sum=a[l]); int mid=l+r>>1;
                build(now<<1,l,mid); build(now<<1|1,mid+1,r); pushup(now);
            }
            #define O beg,end
            inline void modify_mul(int now,int l,int r,int beg,int end,int val)
            {
                if (l>=beg&&r<=end)
                {
                    node[now].tag_mul=1LL*node[now].tag_mul*val%mod;
                    node[now].tag_add=1LL*node[now].tag_add*val%mod;
                    node[now].sum=1LL*node[now].sum*val%mod; return;
                }
                int mid=l+r>>1; pushdown(now,mid-l+1,r-mid);
                if (beg<=mid) modify_mul(now<<1,l,mid,O,val);
                if (end>mid) modify_mul(now<<1|1,mid+1,r,O,val);
                pushup(now);
            }
            inline void modify_add(int now,int l,int r,int beg,int end,int val)
            {
                if (l>=beg&&r<=end)
                {
                    inc(node[now].sum,1LL*val*(r-l+1)%mod);
                    inc(node[now].tag_add,val); return;
                }
                int mid=l+r>>1; pushdown(now,mid-l+1,r-mid);
                if (beg<=mid) modify_add(now<<1,l,mid,O,val);
                if (end>mid) modify_add(now<<1|1,mid+1,r,O,val);
                pushup(now);
            }
            inline int query(int now,int l,int r,int beg,int end)
            {
                if (l>=beg&&r<=end) return node[now].sum;
                int mid=l+r>>1,ret=0; pushdown(now,mid-l+1,r-mid);
                if (beg<=mid) inc(ret,query(now<<1,l,mid,O));
                if (end>mid) inc(ret,query(now<<1|1,mid+1,r,O));
                return ret;
            }
            #undef pushup
            #undef O
    }T;
    

    P3384 【模板】树链剖分

    这个东西大力码就好了,1A没什么问题。

    class Tree_Chain_Dissection
    {
        private:
            int dep[N],size[N],father[N],top[N],id[N],son[N],idx;
            inline void swap(int &x,int &y)
            {
                int t=x; x=y; y=t;
            }
        public:
            #define to e[i].to
            inline void DFS1(int now,int fa)
            {
                dep[now]=dep[fa]+1; size[now]=1; int res=-1;
                for (RI i=head[now];i;i=e[i].nxt) if (to!=fa)
                {
                    DFS1(to,now); size[now]+=size[to]; father[to]=now;
                    if (size[to]>res) res=size[to],son[now]=to;
                }
            }
            inline void DFS2(int now,int topf)
            {
                s[id[now]=++idx]=now; top[now]=topf;
                if (son[now]) DFS2(son[now],topf);
                for (RI i=head[now];i;i=e[i].nxt)
                if (to!=father[now]&&to!=son[now]) DFS2(to,to);
            }
            #undef to
            inline void modify(int x,int y,int val)
            {
                while (top[x]!=top[y])
                {
                    if (dep[top[x]]<dep[top[y]]) swap(x,y);
                    T.modify(1,1,n,id[top[x]],id[x],val);
                    x=father[top[x]];
                }
                if (dep[x]<dep[y]) swap(x,y);
                T.modify(1,1,n,id[y],id[x],val);
            }
            inline int query(int x,int y)
            {
                int ret=0; while (top[x]!=top[y])
                {
                    if (dep[top[x]]<dep[top[y]]) swap(x,y);
                    inc(ret,T.query(1,1,n,id[top[x]],id[x]));
                    x=father[top[x]];
                }
                if (dep[x]<dep[y]) swap(x,y);
                inc(ret,T.query(1,1,n,id[y],id[x]));
                return ret;
            }
            inline void updata(int x,int y)
            {
                T.modify(1,1,n,id[x],id[x]+size[x]-1,y);
            }
            inline int ask(int x)
            {
                return T.query(1,1,n,id[x],id[x]+size[x]-1);
            }
    }L;
    

    P3834 【模板】可持久化线段树 1(主席树)

    刚开始没读排名调了好久。。。第一次发现主席树原来不用写build

    class President_Tree
    {
        private:
            #define P 18
            struct Segment
            {
                int ch[2],size;
            }node[N*P]; int tot;
            #define lc(x) node[x].ch[0]
            #define rc(x) node[x].ch[1]
        public:
            inline void modify(int &now,int lst,int l,int r,int id)
            {
                node[now=++tot]=node[lst]; ++node[now].size;
                if (l==r) return; int mid=l+r>>1;
                if (id<=mid) modify(lc(now),lc(lst),l,mid,id);
                else modify(rc(now),rc(lst),mid+1,r,id);
            }
            inline int query(int lst,int now,int l,int r,int rk)
            {
                if (l==r) return l; int dlt=node[lc(now)].size-node[lc(lst)].size,mid=l+r>>1;
                if (rk<=dlt) return query(lc(lst),lc(now),l,mid,rk);
                else return query(rc(lst),rc(now),mid+1,r,rk-dlt);
            }
            #undef P
            #undef lc
            #undef rc
    }T;
    

    P3369 【模板】普通平衡树

    10号晚上打Treap打到近11点也没调出来。。。

    11号晚上改掉的。然而并没有考数据结构

    class Treap
    {
        private:
            struct treap
            {
                int ch[2],size,cnt,val,dat;
                treap(int Lc=0,int Rc=0,int Size=0,int Cnt=0,int Val=0,int Dat=0)
                {
                    ch[0]=Lc; ch[1]=Rc; size=Size; cnt=Cnt; val=Val; dat=Dat;
                }
            }node[N]; int tot,seed;
            #define lc(x) node[x].ch[0]
            #define rc(x) node[x].ch[1]
            inline int rand(void)
            {
                return seed=(int)seed*482711LL%2147483647;
            }
            inline int create(int val)
            {
                node[++tot]=treap(0,0,1,1,val,rand()); return tot;
            }
            inline void pushup(int now)
            {
                node[now].size=node[lc(now)].size+node[rc(now)].size+node[now].cnt;
            }
            inline void rotate(int &now,int d)
            {
                int t=node[now].ch[d^1]; node[now].ch[d^1]=node[t].ch[d];
                node[t].ch[d]=now; now=t; pushup(node[now].ch[d]); pushup(now);
            }
        public:
            int rt;
            Treap() { seed=233; }
            inline void init(void)
            {
                rt=create(-INF); rc(rt)=create(INF); pushup(rt);
            }
            inline void insert(int &now,int val)
            {
                if (!now) return (void)(now=create(val));
                if (val==node[now].val) return (void)(++node[now].cnt,pushup(now));
                int d=val<node[now].val?0:1; insert(node[now].ch[d],val);
                if (node[node[now].ch[d]].dat>node[now].dat) rotate(now,d^1);
                pushup(now);
            }
            inline void remove(int &now,int val)
            {
                if (!now) return; if (val==node[now].val)
                {
                    if (node[now].cnt>1) return (void)(--node[now].cnt,pushup(now));
                    if (lc(now)||rc(now))
                    {
                        if (!rc(now)||node[lc(now)].dat>node[rc(now)].dat)
                        rotate(now,1),remove(rc(now),val); else 
                        rotate(now,0),remove(lc(now),val);
                        pushup(now);
                    } else now=0; return;
                }
                if (val<node[now].val) remove(lc(now),val); else remove(rc(now),val); pushup(now);
            }
            inline int get_rk(int now,int val)
            {
                if (!now) return 0;
                if (val==node[now].val) return node[lc(now)].size+1; else
                if (val<node[now].val) return get_rk(lc(now),val); else
                return node[lc(now)].size+node[now].cnt+get_rk(rc(now),val);
            }
            inline int get_val(int now,int rk)
            {
                if (!now) return INF;
                if (rk<=node[lc(now)].size) return get_val(lc(now),rk); else
                if (rk<=node[lc(now)].size+node[now].cnt) return node[now].val;
                else return get_val(rc(now),rk-node[lc(now)].size-node[now].cnt);
            }
            inline int get_pre(int now,int val,int pre=0)
            {
                while (now) if (node[now].val<val) pre=node[now].val,now=rc(now);
                else now=lc(now); return pre;
            }
            inline int get_nxt(int now,int val,int nxt=0)
            {
                while (now) if (node[now].val>val) nxt=node[now].val,now=lc(now);
                else now=rc(now); return nxt;
            }
            #undef lc
            #undef rc
    }T;
    

    Postscript

    时间太紧张了才给自己留了两天,刷了一半左右

    感觉今年板子刷的没什么用呵?果然背过的都不考

    退役钦定QWQ感觉放松心态吧

  • 相关阅读:
    Flink开发中的问题
    怎么确定一个Flink job的资源
    Flink统计日活
    Flink读取resource资源文件
    Spark-6-如何缓解消除数据倾斜
    Spark-5-如何定位导致数据倾斜的代码
    Spark-4-为何要处理数据倾斜
    集合遍历删除中遇到问题
    1206
    1205
  • 原文地址:https://www.cnblogs.com/cjjsb/p/9929887.html
Copyright © 2011-2022 走看看