1. 程式人生 > >17.11.10 全是模板的一上午

17.11.10 全是模板的一上午

ack dijkstra n+1 最小 || true define mar tmp

  • 大米餅的左偏樹
  • #include<iostream>
    #include<cstdio>
    #define N 1000005
    using namespace std;
    int n,m,fa[N],l[N],r[N],d[N],v[N];
    bool die[N];
    int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
    int merge(int x,int y)
    {
    	if(!x)return y;if(!y)return x;//樹結構合並的遞歸邊界 
    	if(v[x]>v[y])swap(x,y);//找到兩個樹根中鍵值最小的節點 
    	r[x]=merge(r[x],y);//右兒子插入操作(左偏樹特性),將鍵值較大的樹作為另一個樹的右兒子 
    	if(d[r[x]]>d[l[x]])swap(l[x],r[x]);//維護左偏性質 
    	d[x]=d[r[x]]+1;//記錄dis(左偏樹的基礎信息) 
    	return x;//返回根 
    }
    int main()
    {
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++)scanf("%d",&v[i]);
    	for(int i=1;i<=n;i++)fa[i]=i;d[0]=-1;char ch[10];scanf("%d",&m);
    	
    	for(int i=1;i<=m;i++)
    	{
    		scanf("%s",ch);int x,y;
    		if(ch[0]==‘M‘)//要求:合並團 
    		{
    			scanf("%d%d",&x,&y);
    	    	if(die[x]||die[y])continue;//若最小值已死,則命令無效 
    	    	int p=find(x),q=find(y);//並查集找出左偏樹根 
    	    	if(p!=q)//不是同一棵左偏樹 
    		    {
    				int t=merge(p,q);//左偏樹合並,返回新根 
    				fa[p]=fa[q]=t;//維護並查集 
    	    	}
    	    }
    	    else//要求:詢問團 
    	    {
    	    	scanf("%d",&x);
    	    	if(die[x])printf("0\n");//人已死,命令無效輸出0 
    	    	else 
    	    	{
    	    		int p=find(x);die[p]=1;//找到這個人所在團(左偏樹),將其弄死 
    	    		printf("%d\n",v[p]);//按照題目要求輸出那個人的分數 
    	    		fa[p]=merge(l[p],r[p]);//分最低人死了,將其移出左偏樹,左右兒子合並重建 
    	    		fa[fa[p]]=fa[p];//並查集變成初始化狀態(相當於刪除) 
    	    	}
    	    }
    	}
    	return 0;
    }  
  • P1177 【模板】快速排序
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    int a[100005],n;
    int main()
    {
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    	sort(a+1,a+n+1);
    	for(int i=1;i<n;i++) printf("%d ",a[i]);
    	printf("%d",a[n]);
    	return 0;
    }
    
  • P1439 【模板】最長公共子序列
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    int A[100005],B[100005],tmp[100005];
    int n;
    int LIS(int *a){
    	static int t[100005],p; p=0;
    	for(int i=1;i<=n;i++){
    		if(B[i]>t[p]||t==0) t[++p]=B[i];
    		else{
    			int l=lower_bound(t+1,t+p+1,B[i])-t;
    			t[l]=B[i];
    		}
    	}
    	return p;
    }
    int main()
    {
    	scanf("%d",&n);
    	for(int i=1; i<=n; i++)scanf("%d",&A[i]),tmp[A[i]]=i;
    	for(int i=1; i<=n; i++)scanf("%d",&B[i]),B[i]=tmp[B[i]];
    	int ans=LIS(B);
    	printf("%d",ans);
    	return 0;
    }
    
  • P3366 【模板】最小生成樹 kruskal
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    struct edge{
    	int u,v,w;
    	bool operator <(const edge &rtm) const{
    		return w<rtm.w;	
    	}
    }e[200005];
    int fa[5005];
    int n,m,ans;
    int find(int u){
    	return u==fa[u]?u:fa[u]=find(fa[u]);
    }
    int main()
    {
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=m;i++) scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
    	sort(e+1,e+m+1);
    	for(int i=1;i<=n;i++) fa[i]=i;
    	for(int i=1,need=n-1;i<=m&&need;i++){
    		int u=e[i].u,v=e[i].v,w=e[i].w;
    		int fu=find(u),fv=find(v);
    		if(fu==fv) continue;
    		fa[fv]=fu; need--;
    		ans+=w;
    	}
    	printf("%d",ans);
    	return 0;
    }
    
  • P3366 【模板】最小生成樹 prim
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<queue>
    using namespace std;
    struct node{
        int id,val;
        bool operator <(const node &rtm) const{
            return val>rtm.val;
        }
    };
    struct edge{
        int to,val,next;
    }e[200005*2];
    int head[5005];
    int n,m,ent=2;
    void add(int u,int v,int w){
        e[ent]=(edge){v,w,head[u]};
        head[u]=ent++;
    }
    void cmin(int &a,int b){
        if(a>b) a=b;
    }
    int prim(){
        static int d[5005],ans;
        memset(d,0x3f,sizeof(d));
        priority_queue<node>q; q.push((node){1,0});
        while(!q.empty()){
            int u=(q.top()).id,w=(q.top()).val; q.pop(); 
            if(!(~d[u])) continue;
            ans+=w; d[u]=-1;
            for(int i=head[u];i;i=e[i].next){
                int v=e[i].to;
                if(!(~d[v])) continue;
                cmin(d[v],e[i].val);
                q.push((node){v,d[v]});
            }
        }
        return ans;
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1,u,v,w;i<=m;i++){
            scanf("%d%d%d",&u,&v,&w);
            add(u,v,w); add(v,u,w);
        }
        int ans=prim();
        printf("%d",ans);
        return 0;
    }
  • P3368 【模板】樹狀數組 2
    /*
    	(正反都可以)
    */
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    using namespace std;
    struct BIT{
    	int a[500005],n;
    	void init(int N){
    		n=N; memset(a,0,sizeof(a));
    	}
    	int lowbit(int x){
    		return x&-x;
    	}
    	void add(int l,int r,int w){
    		for(int i=l-1;i;i-=lowbit(i)) a[i]-=w;
    		for(int i=r;i;i-=lowbit(i)) a[i]+=w;
    	}
    	int query(int p){
    		int now=0;
    		for(int i=p;i<=n;i+=lowbit(i)) now+=a[i];
    		return now;
    	}
    }T;
    int a[500005];
    int n,m;
    int main()
    {
    	scanf("%d%d",&n,&m);	T.init(n);
    	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    	int com,x,y,k;
    	for(int i=1;i<=m;i++){
    		scanf("%d",&com);
    		if(com==1){
    			scanf("%d%d%d",&x,&y,&k);
    			T.add(x,y,k);
    		}
    		else{
    			scanf("%d",&x);
    			printf("%d\n",a[x]+T.query(x));
    		}
    	}
    	return 0;
    }
    
  • P3370 【模板】字符串哈希
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    struct node{
        int a,b;
        bool operator ==(const node &rtm) const{
            return a==rtm.a&&b==rtm.b;
        }
        bool operator <(const node &rtm) const {
            return a==rtm.a?b<rtm.b:a<rtm.a;
        }
    }a[10005];
    int hash1(char *s){
        static int mod=19260817,bit=233;
        int now=0;
        for(int i=0;s[i];i++)
            now=(1ll*now*bit+s[i]-0)%mod;
        return now;
    }
    int hash2(char *s){
        static int mod=12356789,bit=79;
        int now=0;
        for(int i=0;s[i];i++)
            now=(1ll*now*bit+s[i]-0)%mod;
        return now;
    }
    int n;
    int main()
    {
        char s[1505];
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%s",s);
            a[i]=(node){hash1(s),hash2(s)};
        }
        sort(a+1,a+n+1);
        n=unique(a+1,a+n+1)-a-1;
        printf("%d",n);
        return 0;
    }
    
  • P3371 【模板】單源最短路徑
    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #define node(a,b) (node){a,b}
    using namespace std;
    struct node{
        int id,val;
        bool operator <(const node &rtm) const{
            return val>rtm.val;
        }
    };
    struct edge{
        int to,val,next;
    }e[500005];
    int head[10005];
    int n,m,ent=2,S;
    void add(int u,int v,int w){
        e[ent]=(edge){v,w,head[u]};
        head[u]=ent++;
    }
    void Dijkstra(){
        static int dis[10005];
        static bool vis[10005];
        priority_queue<node> q;
        for(int i=1;i<=n;i++) dis[i]=2147483647;
        q.push(node(S,0)); dis[S]=0;
        while(!q.empty()){
            int u=(q.top()).id; q.pop();
            if(vis[u]) continue;
            vis[u]=1;
            for(int i=head[u];i;i=e[i].next){
                int v=e[i].to;
                if(dis[v]<=dis[u]+e[i].val) continue;
                dis[v]=dis[u]+e[i].val;
                q.push(node(v,dis[v]));
            }
        }
        for(int i=1;i<=n;i++) printf("%d ",dis[i]);
    }
    void SPFA(){
        static int dis[10005];
        static bool inq[10005];
        deque<int>q;
        for(int i=1;i<=n;i++) dis[i]=2147483647;
        q.push_back(S); dis[S]=0; inq[S]=1;
        while(!q.empty()){
            int u=q.front(); q.pop_front(); inq[u]=0;
            for(int i=head[u];i;i=e[i].next){
                int v=e[i].to;
                if(dis[v]<=dis[u]+e[i].val) continue;
                dis[v]=dis[u]+e[i].val;
                if(inq[v]) continue; inq[v]=1;
                if(!q.empty()&&dis[q.front()]>dis[v]) q.push_front(v);
                else q.push_back(v);
            }
        }
        for(int i=1;i<=n;i++) printf("%d ",dis[i]);
    }
    int main()
    {
        scanf("%d%d%d",&n,&m,&S);
        for(int i=1,u,v,w;i<=m;i++){
            scanf("%d%d%d",&u,&v,&w);
            add(u,v,w);
        }
        //Dijkstra();
        SPFA();
        return 0;
    }
  • P3375 【模板】KMP字符串匹配
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    using namespace std;
    char A[1000005],B[1000005];
    int nxt[1000005];
    void get_nxt(char *s){
    	nxt[0]=-1; int k=-1,j=0;
    	while(s[j]){
    		if(k==-1||s[j]==s[k]){
    			k++; j++; nxt[j]=k;
    		}
    		else k=nxt[k];
    	}
    }
    void matching(char *T,char *S){
    	int i=0,j=0;
    	while(T[i]){
    		if(j==-1||T[i]==S[j]) i++,j++;
    		else j=nxt[j];
    		if(~j&&!S[j]) printf("%d\n",i-j+1);
    	}
    	for(int i=1;S[i-1];i++) printf("%d ",nxt[i]);
    }
    int main()
    {
    	scanf("%s",A); scanf("%s",B);
    	get_nxt(B);
    	matching(A,B);
    	return 0;
    }
    
  • P3383 【模板】線性篩素數
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    using namespace std;
    bool iscom[10000005];
    int prim[10000005],cnt;
    void Get(int N){
    	iscom[1]=1;
    	for(int i=2;i<=N;i++){
    		if(!iscom[i]) prim[++cnt]=i;
    		for(int j=1;j<=cnt&&i<=N/prim[j];j++){
    			iscom[i*prim[j]]=1;
    			if(i%prim[j]==0) break;
    		}
    	}
    }
    int main()
    {
    	int n,m;
    	scanf("%d%d",&n,&m);
    	Get(n);
    	while(m--){
    		scanf("%d",&n);
    		if(iscom[n]) puts("No");
    		else puts("Yes");
    	}
    	return 0;
    }
    
  • P3386 【模板】二分圖匹配
    /*
    	匈牙利算法匹配時,那個vis標記是遇到一個v就標記,而不是進入一個dfs才標記。 
    */
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    using namespace std;
    struct edge{
    	int to,next;
    }e[1005*1005*2];
    int head[2005],match[2005],vis[2005];
    int n,m,ent=2,tim,ans,ee;
    void add(int u,int v){
    	e[ent]=(edge){v,head[u]};
    	head[u]=ent++;
    }
    bool dfs(int u){
    	for(int i=head[u];i;i=e[i].next){
    		int v=e[i].to;
    		if(vis[v]==tim) continue;
    		vis[v]=tim;
    		if(!match[v]||dfs(match[v])){
    			match[v]=u;
    			return 1;
    		}
    	}
    	return 0;
    }
    int main()
    {
    	scanf("%d%d%d",&n,&m,&ee);
    	for(int i=1,u,v;i<=ee;i++){
    		scanf("%d%d",&u,&v); 
    		if(u>n||v>m)  continue;
    		v+=n;
    		add(u,v); add(v,u);
    	}
    	for(int i=1;i<=n+m;i++){
    		tim++;
    		if(dfs(i)) ans++;
    	}
    	printf("%d",ans/2);
    	return 0;
    }
    
  • P3808 【模板】AC自動機(簡單版)
    #include<cstdio>
    #include<queue>
    #include<cstring>
    #include<iostream>
    using namespace std;
    struct Trie{
    	int next,last,val;
    	int ch[30];
    }T[1000006];
    char s[1000006];
    int n,sz=0,ans;
    int idx(char ch){
    	return ch-‘a‘;
    }
    void add(char *S){
    	int u=0,l=strlen(S);
    	for(int i=0;i<l;i++){
    		int c=idx(S[i]);
    		if(!T[u].ch[c]) T[u].ch[c]=++sz;
    		u=T[u].ch[c];
    	}
    	T[u].val++;
    }
    void build(){
    	queue<int>q;
    	for(int i=0;i<26;i++) if(T[0].ch[i]) q.push(T[0].ch[i]);
    	while(!q.empty()){
    		int u=q.front(); q.pop();
    		for(int i=0;i<26;i++){
    			if(!T[u].ch[i]) T[u].ch[i]=T[T[u].next].ch[i];
    			else{
    				int v=T[u].ch[i];
    				T[v].next=T[T[u].next].ch[i];
    				T[v].last=T[T[v].next].val?T[v].next:T[T[v].next].last;
    				q.push(v);
    			}
    		}
    	}
    }
    void get(int j){
    	if(!j||!T[j].val) return;
    	ans+=T[j].val; T[j].val=0;
    	get(T[j].last);
    }
    void match(char *S){
    	int l=strlen(S); int j=0;
    	for(int i=0;i<l;i++)
    	{
    		int c=idx(S[i]);
    		j=T[j].ch[c];
    		if(T[j].val) get(j);
    		else if(T[j].last) get(T[j].last);
    	}
    }
    int main()
    {
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++){
    		scanf("%s",s);
    		add(s);
    	}
    	build(); scanf("%s",s);
    	match(s);
    	printf("%d",ans);
    	return 0;
    }
    
  • P3811 【模板】乘法逆元
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    using namespace std;
    long long inv[3000006],mod,n; 
    int main()
    {
    	scanf("%lld%lld",&n,&mod);
    	inv[1]=1;printf("%lld\n",inv[1]);
    	for(int i=2;i<=n;i++){
    		inv[i]=( (-(mod/i)*inv[mod%i]) %mod+mod)%mod;
    		printf("%lld\n",inv[i]);
    	}
    	return 0;
    }
    

17.11.10 全是模板的一上午