HDU 4891 The Great Pan
注册标题 他怎么说,你怎么样 需要注意的是乘法时,它会爆炸int
代码:
#include
#include
#include
#include
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;
}
题意:
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
#include
#include
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;
}
题意:
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
#include
#include
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;
}
版权声明:本文博客原创文章,博客,未经同意,不得转载。