题目地址: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;
}