首页 > 代码库 > 2014多校联合三 (HDU 4888 HDU 4891 HDU 4893)

2014多校联合三 (HDU 4888 HDU 4891 HDU 4893)

HDU 4891 The Great Pan

签到题  他怎么说你就怎么做就好了  注意做乘法时候会爆int


代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;

int n;
char s[2000000];
int flag1, flag2, sp, ansflag;
LL ans, tmp;

int main() {
	while (scanf("%d", &n) != EOF) {
		getchar();
		ans = 1;
		tmp = 0;
		flag1 = 0;
		flag2 = 0;
		ansflag = 1;
		for (int l = 1; l <= n; l++) {
			gets(s);
			int len = strlen(s);
			if (ansflag == 0)
				continue;
			for (int i = 0; i < len; i++) {
				if (flag1 == 0 && flag2 == 0 && s[i] == '{') {
					flag1 = 1;
					tmp = 0;
				} else if (flag1 == 1 && s[i] == '|') {
					tmp++;
				} else if (flag1 == 1 && s[i] == '}') {
					flag1 = 0;
					ans *= (tmp + 1);
					tmp = 1;
					if (ans > 1e5) {
						ansflag = 0;
						break;
					}
				} else if (flag1 == 0 && flag2 == 0 && s[i] == '$') {
					flag2 = 1;
					sp = 0;
					tmp = 0;
				} else if (flag2 == 1) {
					if (s[i] == '$') {
						if (sp == 1) {
							ans *= (tmp + 1);
							if (ans > 1e5) {
								ansflag = 0;
								break;
							}
						}
						flag2 = 0;
						tmp = 0;
					} else if (sp == 1 && s[i] != ' ') {
						ans *= (tmp + 1);
						if (ans > 1e5) {
							ansflag = 0;
							break;
						}
						sp = 0;
						tmp = 0;
					} else if (sp == 0 && s[i] == ' ') {
						tmp = 1;
						sp = 1;
					} else if (sp == 1 && s[i] == ' ') {
						tmp++;
					}
				}

			}

		}
		if (ansflag)
			printf("%d\n", ans);
		else
			printf("doge\n");
	}
	return 0;
}


HDU 4893 Wow! Such Sequence!
题意:

n个数一开始都是0  你有三种操作  1操作在k位置加d  2操作输出[l,r]区间的和  3操作把[l,r]内的所有数变成离它最近最小的斐波那契数


思路:

操作1、2就是线段树基本  那么3怎么搞? 为了不超时显然要延迟更新  那么如果更新到[l,r]区间我们如何更改值呢

其实问题可以被巧妙的存储数据解决

我们记val为点上的值  toval为离他最近的斐波那契数  sum为val的和  tosum为toval的和

那么每当3操作时  我们只需要让区间的val和sum等于toval和tosum即可  在1操作时也要注意更新toval和tosum


代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
#define N 100010
#define L(x) (x<<1)
#define R(x) ((x<<1)|1)
#define last 92
#define star 1

struct node {
	int l, r, lazy;
	LL val, toval, sum, tosum;
} nd[N * 4];
LL F[N];
int n, m;

LL cal(LL x) {
	if (x < 0)
		return -x;
	return x;
}

void up(int i) {
	nd[i].sum = nd[L(i)].sum + nd[R(i)].sum;
	nd[i].tosum = nd[L(i)].tosum + nd[R(i)].tosum;
}

void down(int i) {
	if (nd[i].lazy) {
		nd[L(i)].val = nd[L(i)].toval;
		nd[L(i)].sum = nd[L(i)].tosum;
		nd[L(i)].lazy = 1;
		nd[R(i)].val = nd[R(i)].toval;
		nd[R(i)].sum = nd[R(i)].tosum;
		nd[R(i)].lazy = 1;
		nd[i].lazy = 0;
	}
}

void init(int l, int r, int i) {
	nd[i].l = l;
	nd[i].r = r;
	nd[i].lazy = 0;
	nd[i].val = 0;
	nd[i].toval = 0;
	nd[i].sum = 0;
	if (l == r) {
		nd[i].toval = 1;
		nd[i].tosum = 1;
		return;
	}
	int mid = (l + r) >> 1;
	init(l, mid, L(i));
	init(mid + 1, r, R(i));
	up(i);
}

void add(int pos, int val, int i) {
	if (pos == nd[i].l && pos == nd[i].r) {
		int idx1, idx2;
		nd[i].val += val;
		idx1 = lower_bound(F + star, F + last, nd[i].val) - F;
		idx2 = idx1 - 1;
		if (cal(F[idx1] - nd[i].val) < cal(F[idx2] - nd[i].val)) {
			nd[i].toval = nd[i].tosum = F[idx1];
			nd[i].sum = nd[i].val;
		} else {
			nd[i].toval = nd[i].tosum = F[idx2];
			nd[i].sum = nd[i].val;
		}
		nd[i].lazy = 0;
		return;
	}
	down(i);
	int mid = (nd[i].l + nd[i].r) >> 1;
	if (pos <= mid)
		add(pos, val, L(i));
	else
		add(pos, val, R(i));
	up(i);
}

void update(int l, int r, int i) {
	if (l == nd[i].l && r == nd[i].r) {
		nd[i].val = nd[i].toval;
		nd[i].sum = nd[i].tosum;
		nd[i].lazy = 1;
		return;
	}
	down(i);
	int mid = (nd[i].l + nd[i].r) >> 1;
	if (r <= mid)
		update(l, r, L(i));
	else if (l > mid)
		update(l, r, R(i));
	else {
		update(l, mid, L(i));
		update(mid + 1, r, R(i));
	}
	up(i);
}

LL query(int l, int r, int i) {
	if (l == nd[i].l && r == nd[i].r) {
		//if(nd[i].lazy) return nd[i].tosum;
		//else return nd[i].sum;
		return nd[i].sum;
	}
	down(i);
	int mid = (nd[i].l + nd[i].r) >> 1;
	LL res = 0;
	if (r <= mid)
		res = query(l, r, L(i));
	else if (l > mid)
		res = query(l, r, R(i));
	else
		res = query(l, mid, L(i)) + query(mid + 1, r, R(i));
	if (nd[i].l != nd[i].r)
		up(i);
	return res;
}

void dfs(int i) {
	printf("l %d r %d lazy %d val %I64d toval %I64d sum %I64d tosum %I64d\n",
			nd[i].l, nd[i].r, nd[i].lazy, nd[i].val, nd[i].toval, nd[i].sum,
			nd[i].tosum);
	if (nd[i].l == nd[i].r)
		return;
	dfs(L(i));
	dfs(R(i));
}

int main() {
	int i, op, l, r;
	F[0] = F[1] = 1;
	for (i = 2; i < 100; i++)
		F[i] = F[i - 1] + F[i - 2];
	//91 7540113804746346429
	// F [0 ~ 91]
	while (~scanf("%d%d", &n, &m)) {
		init(1, n, 1);
		for (i = 1; i <= m; i++) {
			scanf("%d%d%d", &op, &l, &r);
			if (op == 1)
				add(l, r, 1);
			else if (op == 2)
				printf("%I64d\n", query(l, r, 1));
			else
				update(l, r, 1);
		}
		//dfs(1);
	}
	return 0;
}


HDU 4888 Redraw Beautiful Drawings

题意:

n*m的格子里面有数字0~K  现给出每一行和每一列的和  求格子里的值(唯一解时输出值  可能多解或无解)


思路:

首先要想到这题可以用网络流搞  不管从数据范围入手还是真的有思路

接着建图  (1)S->行 容量sum行  (2)列->T 容量sum列  (3)行->列 容量K  跑最大流如果满流则至少一个解

理解一下这个流就是说从行x进去的流量  经过(x,y)格子传递后  从列y出去  那么这时如果满流不就是满足题意么

接下来判断是否唯一解  可以想到  假设解不唯一  则有以下结论

从某个点开始  在这个点+g  在与它同行的某个点-g  再在新点的同列的某个点+g  一直不断延续这条路 类似这样:

+g     -g

-g      +g

形成一个新的解  像不像从某个点搬运了一点东西??  然后搬一圈!!  就是这个圈所以解不唯一!!

那么我们在残余网络中dfs  如果找到一个长度>2的圈  那么必然有其他解(按着这个圈搬一搬!)

dfs最暴力即可  这是队友说的  基本都是4个点就围成圈了  点数不可能太多


PS:这是一道卡dinic时间的题! 用sap可过!

如果有巨巨用dinic过了麻烦教我一下…  从刘大师那里学来的dinic应该不会写搓…(自信???


代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

const int MAXN = 810;
const int MAXM = 810 * 810 * 2;
const int INF = 0x3f3f3f3f;

struct Node {
	int from, to, next;
	int cap;
} edge[MAXM];
int tol;
int head[MAXN];
int dep[MAXN];
int gap[MAXN];
int n;

void init() {
	tol = 0;
	memset(head, -1, sizeof(head));
}

void addedge(int u, int v, int w) {
	edge[tol].from = u;
	edge[tol].to = v;
	edge[tol].cap = w;
	edge[tol].next = head[u];
	head[u] = tol++;
	edge[tol].from = v;
	edge[tol].to = u;
	edge[tol].cap = 0;
	edge[tol].next = head[v];
	head[v] = tol++;
}
void BFS(int start, int end) {
	memset(dep, -1, sizeof(dep));
	memset(gap, 0, sizeof(gap));
	gap[0] = 1;
	int que[MAXN];
	int front, rear;
	front = rear = 0;
	dep[end] = 0;
	que[rear++] = end;
	while (front != rear) {
		int u = que[front++];
		if (front == MAXN)
			front = 0;
		for (int i = head[u]; i != -1; i = edge[i].next) {
			int v = edge[i].to;
			if (dep[v] != -1)
				continue;
			que[rear++] = v;
			if (rear == MAXN)
				rear = 0;
			dep[v] = dep[u] + 1;
			++gap[dep[v]];
		}
	}
}
int SAP(int start, int end) {
	int res = 0;
	BFS(start, end);
	int cur[MAXN];
	int S[MAXN];
	int top = 0;
	memcpy(cur, head, sizeof(head));
	int u = start;
	int i;
	while (dep[start] < n) {
		if (u == end) {
			int temp = INF;
			int inser;
			for (i = 0; i < top; i++)
				if (temp > edge[S[i]].cap) {
					temp = edge[S[i]].cap;
					inser = i;
				}
			for (i = 0; i < top; i++) {
				edge[S[i]].cap -= temp;
				edge[S[i] ^ 1].cap += temp;
			}
			res += temp;
			top = inser;
			u = edge[S[top]].from;
		}
		if (u != end && gap[dep[u] - 1] == 0)
			break;
		for (i = cur[u]; i != -1; i = edge[i].next)
			if (edge[i].cap != 0 && dep[u] == dep[edge[i].to] + 1)
				break;
		if (i != -1) {
			cur[u] = i;
			S[top++] = i;
			u = edge[i].to;
		} else {
			int min = n;
			for (i = head[u]; i != -1; i = edge[i].next) {
				if (edge[i].cap == 0)
					continue;
				if (min > dep[edge[i].to]) {
					min = dep[edge[i].to];
					cur[u] = i;
				}
			}
			--gap[dep[u]];
			dep[u] = min + 1;
			++gap[dep[u]];
			if (u != start)
				u = edge[S[--top]].from;
		}
	}
	return res;
}

int vis[MAXN];
bool sol(int u, int fa) {
	int i, v;
	vis[u] = 1;
	for (i = head[u]; ~i; i = edge[i].next) {
		v = edge[i].to;
		if (!edge[i].cap || v == fa)
			continue;
		if (vis[v] || sol(v, u))
			return true;
	}
	vis[u] = 0;
	return false;
}

bool findcircle(int fn) {
	memset(vis, 0, sizeof(vis));
	for (int i = 1; i <= fn; i++) {
		vis[i] = 1;
		if (sol(i, i))
			return true;
		vis[i] = 0;
	}
	return false;
}

int sumx[MAXN], sumy[MAXN];
int main() {
	int i, j, k, n1, n2, K, amt, ans;
	while (~scanf("%d%d%d", &n1, &n2, &K)) {
		init();
		sumx[0] = sumy[0] = 0;
		for (i = 1; i <= n1; i++) {
			scanf("%d", &sumx[i]);
			sumx[0] += sumx[i];
		}
		for (i = 1; i <= n2; i++) {
			scanf("%d", &sumy[i]);
			sumy[0] += sumy[i];
		}
		if (sumx[0] != sumy[0]) {
			puts("Impossible");
			continue;
		}
		for (i = 1; i <= n1; i++) {
			for (j = 1; j <= n2; j++)
				addedge(i, n1 + j, K);
		}
		amt = tol;
		for (i = 1; i <= n1; i++)
			addedge(0, i, sumx[i]);
		for (i = 1; i <= n2; i++)
			addedge(n1 + i, n1 + n2 + 1, sumy[i]);
		n = n1 + n2 + 2;
		ans = SAP(0, n1 + n2 + 1);
		if (ans != sumx[0]) {
			puts("Impossible");
			continue;
		}
		if (findcircle(n1))
			puts("Not Unique");
		else {
			puts("Unique");
			for (i = 0; i < amt; i += 2) {
				printf("%d", K - edge[i].cap);
				if (edge[i].to == n1 + n2)
					putchar('\n');
				else
					putchar(' ');
			}
		}
	}
	return 0;
}