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

题目地址:NOIP RP++

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

#include
#include
#include
#include
#include
#include
#define lson p<<1
#define rson p<<1|1
using 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
#include
#include
#include
#include
#include
#include
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
#include
#include
#include
#include
#include
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
#include
#include
#include
#include
#include
#include
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<
        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
#include
#include
#include
#include
#include
#include
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
#include
#include
#include
#include
#include
#include
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;
}

你可能感兴趣的:(洛谷,------OJ------)