[洛谷模板大赛]题解 模板整理QAQ

来源:互联网 发布:java 代码整洁之道 编辑:程序博客网 时间:2024/05/17 07:08

题目地址:NOIP RP++

题目描述不用说,都是交模板就能AC的,昨晚就A了4个题因为时间不太够了……
最近也想整理模板,看到这么个模板大赛自然是把持不住辣~
除了T2平衡树不会做之外其他的都可以,T5好像是递归版Spfa,现学了一下,其实思想都一样,不用学,其他的没什么了,看模板~
T1:线段树:

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<queue>#include<stack>#define lson p<<1#define rson p<<1|1using namespace std;typedef long long LL;const int SIZE = 500010;struct Tree{    int l,r;    LL sum,add;}tree[SIZE<<2];void build(int p,int l,int r){    tree[p].l = l,tree[p].r = r;    if(l == r)  return ;    int mid = (l + r) >> 1;    build(lson,l,mid);    build(rson,mid+1,r);}inline void RD(int &x){    x = 0;  char c; c = getchar();    bool flag = 0;    if(c == '-')    flag = 1;    while(c < '0' || c > '9')    {        if(c == '-')    flag = 1;        c = getchar();    }    while(c >= '0' && c <= '9') x = (x << 1) + (x << 3) + c - '0',c = getchar();    if(flag)    x = -x;}void spread(int p){    if(tree[p].add)    {        tree[lson].sum += (LL)(tree[lson].r - tree[lson].l + 1) * tree[p].add;        tree[rson].sum += (LL)(tree[rson].r - tree[rson].l + 1) * tree[p].add;        tree[lson].add += tree[p].add;        tree[rson].add += tree[p].add;        tree[p].add = 0;    }}void change(int p,int l,int r,int x){    if(l <= tree[p].l && tree[p].r <= r)    {        tree[p].sum += (LL)x * (tree[p].r - tree[p].l + 1);        tree[p].add += (LL)x;        return ;    }    spread(p);    int mid = (tree[p].l + tree[p].r) >> 1;    if(l <= mid)    change(lson,l,r,x);    if(mid < r)     change(rson,l,r,x);    tree[p].sum = tree[lson].sum + tree[rson].sum;}LL ask(int p,int l,int r){    if(l <= tree[p].l && tree[p].r <= r)    return tree[p].sum;    spread(p);    LL ans = 0;    int mid = (tree[p].l + tree[p].r) >> 1;    if(l <= mid)    ans += ask(lson,l,r);    if(mid < r)     ans += ask(rson,l,r);    return ans;}int n,m,q,l,r;int x;int main(){    RD(n);    RD(m);    build(1,1,n);    while(m--)    {        RD(q);        if(q == 2)        {            RD(l);            RD(r);            RD(x);            change(1,l,r,x);        }        if(q == 1)        {            RD(l);            RD(r);            printf("%lld\n",ask(1,l,r));        }    }    return 0;}

T2:平衡树(听说线段树能做我也没仔细看……)
T3:堆
需要注意一下,把删除操作替换掉,就是每次要删除时直接标记那个数,等到查询那个数的时候再删除那个数,这样正确性仍然是能保证的~

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<queue>#include<stack>#include<map>using namespace std;typedef long long LL;map <int,bool> vis;inline void RD(int &x){    x = 0;  char c; c = getchar();    bool flag = 0;    if(c == '-')    flag = 1;    while(c < '0' || c > '9')    {        if(c == '-')    flag = 1;        c = getchar();    }    while(c >= '0' && c <= '9') x = (x << 1) + (x << 3) + c - '0',c = getchar();    if(flag)    x = -x;}priority_queue <int> q;int n,a;int main(){    RD(n);    while(n--)    {        RD(a);        if(a > 0)   q.push(a);        else if(a == 0)        {            while(vis[q.top()]) q.pop();            printf("%d\n",q.top());        }        else if(a < 0)  vis[-a] = 1;    }    return 0;}

T4:二分图的最大匹配

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<queue>#include<stack>using namespace std;typedef long long LL;const int SIZE = 500010;struct Edge{int to;}edges[SIZE];int head[SIZE],next[SIZE],tot;void build(int f,int t){    edges[++tot].to = t;    next[tot] = head[f];    head[f] = tot;}inline void RD(int &x){    x = 0;  char c; c = getchar();    bool flag = 0;    if(c == '-')    flag = 1;    while(c < '0' || c > '9')   {if(c == '-')   {flag = 1;} c = getchar();}    while(c >= '0' && c <= '9') x = (x << 1) + (x << 3) + c - '0',c = getchar();}bool vis[SIZE];int connect[SIZE << 1];bool dfs(int u){    for(int i = head[u];i;i = next[i])    {        int v = edges[i].to;        if(!vis[v])        {            vis[v] = 1;            if(!connect[v] || dfs(connect[v]))            {                connect[v] = u;                return true;            }        }    }    return false;}int n,m,k,a,b;int main(){    RD(n),RD(m),RD(k);    int mx = max(n,m);    while(k --)    {        RD(a),RD(b);        build(a,b+mx);    }    int cnt = 0;    for(int i = 1;i <= n;i ++)    {        memset(vis,0,sizeof(vis));        if(dfs(i))  cnt ++;    }    printf("%d\n",cnt);    return 0;}

T5:最短路
注意开long long ,以及把变量开在外面这个细节~

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<queue>#include<stack>#include<cmath>using namespace std;typedef long long LL;const int SIZE = 200010;const LL INF = 2147483647233LL;struct Edge{int to;LL dist;}edges[SIZE];int head[SIZE],next[SIZE],tot;void build(int f,int t,LL d){    edges[++tot].to = t;    edges[tot].dist = d;    next[tot] = head[f];    head[f] = tot;}deque <int> q;LL dist[SIZE];bool vis[SIZE];int n,m,s,t;void spfa(){    for(int i = 1;i <= n;i ++)  dist[i] = INF;    q.push_back(s);    vis[s] = 1;    dist[s] = 0;    while(!q.empty())    {        int f = q.front();        q.pop_front();        vis[f] = 0;        for(int i = head[f];i;i = next[i])        {            int v = edges[i].to;            if(dist[v] > dist[f] + edges[i].dist)            {                dist[v] = dist[f] + edges[i].dist;                if(!vis[v])                {                    vis[v] = 1;                    if(!q.empty() && dist[v] < dist[q.front()]) q.push_front(v);                    else    q.push_back(v);                }            }        }    }}int a,b;LL c;int main(){    scanf("%d%d",&n,&m);    for(int i = 1;i <= m;i ++)    {        scanf("%d %d %lld",&a,&b,&c);//      cout<<a<<" "<<b<<" "<<c<<endl;        build(a,b,c);    }    s = 1,t = n;    spfa();    if(dist[t] == INF)  puts("-1");    else printf("%lld\n",dist[t]);    return 0;}

T6:dfs版的spfa判断负环

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<queue>#include<stack>#include<cmath>using namespace std;typedef long long LL;typedef double DB;const int SIZE = 500010;struct Edge{int to,dist;}edges[SIZE];int head[SIZE],next[SIZE],tot;void build(int f,int t,int d){    edges[++tot].to = t;    edges[tot].dist = d;    next[tot] = head[f];    head[f] = tot;}int n,m,a,b,c;bool vis[SIZE];int dist[SIZE];bool flag = 0;void spfa(int u){    if(flag)    return ;    for(int i = head[u];i;i = next[i])    {        int v = edges[i].to;        if(dist[v] > dist[u] + edges[i].dist)        {            if(vis[v])  flag = 1;            dist[v] = dist[u] + edges[i].dist;            if(!vis[v])            {                vis[v] = 1;                spfa(v);                vis[v] = 0;            }        }    }}int main(){    int t;    scanf("%d",&t);    while(t--)    {        tot = 0;        memset(head,0,sizeof(head));        memset(edges,0,sizeof(edges));        memset(next,0,sizeof(next));        scanf("%d%d",&n,&m);        for(int i = 1;i <= m;i ++)        {            scanf("%d%d%d",&a,&b,&c);            build(a,b,c);            if(c >= 0)  build(b,a,c);        }        flag = 0;        memset(dist,64,sizeof(dist));        for(int i = 1;i <= n;i ++)        {            if(!vis[i])            {                spfa(i);                if(flag)    {puts("YE5");break;}            }        }        if(!flag)   puts("N0");    }    return 0;}

T7:tarjian求割点

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<queue>#include<stack>#include<cmath>using namespace std;typedef long long LL;typedef double DB;const int SIZE = 200010;int n,m;struct Edge{int to;}edges[SIZE];int head[SIZE],next[SIZE],tot;void build(int f,int t){    edges[++tot].to = t;    next[tot] = head[f];    head[f] = tot;}int dfs_clock,low[SIZE],pre[SIZE];bool iscut[SIZE];bool dfs(int u,int fa){    low[u] = pre[u] = ++dfs_clock;    int child = 0;    for(int i = head[u];i;i = next[i])    {        int v = edges[i].to;        if(v == fa) continue;        if(!pre[v])        {            child ++;            dfs(v,u);            low[u] = min(low[u],low[v]);            if(pre[u] <= low[v])    iscut[u] = true;        }        else if(pre[v] < pre[u])        {            low[u] = min(low[u],pre[v]);        }    }    if(child <= 1 && fa < 0)    iscut[u] = false;}int a,b;int main(){    scanf("%d%d",&n,&m);    for(int i = 1;i <= m;i ++)    {        scanf("%d%d",&a,&b);        build(a,b);        build(b,a);    }    for(int i = 1;i <= n;i ++) if(!pre[i])  dfs(i,-1);    int cnt = 0;    for(int i = 1;i <= n;i ++)  if(iscut[i])    cnt ++;    printf("%d\n",cnt);    return 0;}
0 0