颓废
颓废啦,文化课又爆炸啦。
继续刷水题啦
BZOJ1452 [JSOI2009]Count
震惊,JSOI竟有这种傻逼题!
#prag\
ma GCC optimize("O3")
#include <cstdio>
#include <cstring>
#define lowbit(x) (x & -x)
const int MAXN = 300;
using namespace std;
int n, m;
class Bit {
public :
Bit() {memset(c, 0, sizeof(c));}
void update(int x, int y, int num, int val);
int GetSum(int x, int y, int num);
int query(int a, int b, int x, int y, int num);
private :
int c[MAXN + 5][MAXN + 5][100 + 5];
}T;
void Bit::update(int x, int y, int num, int val) {
for (int i = x; i <= n; i += lowbit(i))
for (int j = y; j <= m; j += lowbit(j))
c[i][j][num] += val;
}
int Bit::GetSum(int x, int y, int num) {
int ret = 0;
for (int i = x; i; i -= lowbit(i))
for (int j = y; j; j -= lowbit(j))
ret += c[i][j][num];
return ret;
}
int Bit::query(int a, int b, int x, int y, int num) {
// cout << '*' << a << ' ' << b << ' ' << x << ' ' << y << ' ' << GetSum(x, y, num) << endl;
return GetSum(x, y, num) - GetSum(a - 1, y, num) - GetSum(x, b - 1, num) + GetSum(a - 1, b - 1, num);
}
int arr[MAXN + 5][MAXN + 5];
int main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= m; ++j)
scanf("%d", &arr[i][j]), T.update(i, j, arr[i][j], 1);
int q; scanf("%d", &q);
while (q--) {
int opt, a, b, x, y, num; scanf("%d%d%d", &opt, &a, &b);
switch(opt) {
case 1 : {
scanf("%d", &num), T.update(a, b, arr[a][b], -1);
arr[a][b] = num, T.update(a, b, arr[a][b], 1);
break;
}
case 2 : scanf("%d%d%d", &x, &y, &num), printf("%d\n", T.query(a, x, b, y, num)); break;
}
}
return 0;
}
BZOJ3343 教主的魔法
太经典的分块了,一直没做。
#include <iostream>
#include <cstdio>
#include <vector>
#include <cmath>
#include <algorithm>
const int MAXN = 1e6;
using namespace std;
inline int read() {
int x = 0, w = 1; char c = ' ';
while (c < '0' || c > '9') {c = getchar(); if (c == '-') w = -1;}
while (c >= '0' && c <= '9') x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
return x * w;
}
int n, block, num, a[MAXN + 5], l[MAXN + 5], r[MAXN + 5], delta[MAXN + 5], belong[MAXN + 5];
vector < int > V[MAXN + 5];
void build() {
block = sqrt(n), num = n / block;
if (n % block) ++num;
for (int i = 1; i <= num; ++i)
l[i] = (i - 1) * block + 1, r[i] = i * block;
r[num] = n;
for (int i = 1; i <= n; ++i)
belong[i] = (i - 1) / block + 1, V[belong[i]].push_back(a[i]);
for (int i = 1; i <= num; ++i)
sort(V[i].begin(), V[i].end());
}
void rebuild(int x) {
V[x].clear();
for (int i = l[x]; i <= r[x]; ++i)
V[x].push_back(a[i]);
sort(V[x].begin(), V[x].end());
}
void update(int x, int y, int val) {
if (belong[x] == belong[y])
for (int i = x; i <= y; ++i)
a[i] += val;
else {
for (int i = x; i <= r[belong[x]]; ++i)
a[i] += val;
for (int i = belong[x] + 1; i < belong[y]; ++i)
delta[i] += val;
for (int i = l[belong[y]]; i <= y; ++i)
a[i] += val;
}
rebuild(belong[x]), rebuild(belong[y]);
}
inline int calc(int x, int val) {
return V[x].size() - (lower_bound(V[x].begin(), V[x].end(), val) - V[x].begin());
}
int query(int x, int y, int val) {
int ret = 0;
if (belong[x] == belong[y]) {
for (int i = x; i <= y; ++i)
if (a[i] + delta[belong[i]] >= val) ++ret;
}
else {
for (int i = x; i <= r[belong[x]]; ++i)
if (a[i] + delta[belong[i]] >= val) ++ret;
for (int i = belong[x] + 1; i < belong[y]; ++i)
ret += calc(i, val - delta[i]);
for (int i = l[belong[y]]; i <= y; ++i)
if (a[i] + delta[belong[i]] >= val) ++ret;
}
return ret;
}
int main() {
n = read(); int q = read();
for (int i = 1; i <= n; ++i)
a[i] = read();
build();
while (q--) {
char c = getchar(); while (c != 'A' && c != 'M') c = getchar();
int x = read(), y = read(), val = read();
switch(c) {
case 'M' : update(x, y, val); break;
case 'A' : printf("%d\n", query(x, y, val)); break;
}
}
return 0;
}
[HNOI2003]激光炸弹
这种题还算省选题?
二维前缀和水过。
卡内存有毒。
#include <iostream>
#include <cstdio>
#define min(a, b) (a < b ? a : b)
#define max(a, b) (a < b ? b : a)
const int MAXN = 5005;
using namespace std;
inline int read() {
int x = 0, w = 1; char c = ' ';
while (c < '0' || c > '9') {c = getchar(); if (c == '-') w = -1;}
while (c >= '0' && c <= '9') x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
return x * w;
}
short a[MAXN + 5][MAXN + 5];
int S[MAXN + 5][MAXN + 5];
int main() {
int n = read(), r = read(), x, y, num; int Ans = 0;
for (int i = 1; i <= n; ++i) {
x = read(), y = read(), num = read();
a[x + 1][y + 1] = num;
}
for (int i = 1; i <= MAXN + 1; ++i)
for (int j = 1; j <= MAXN + 1; ++j)
S[i][j] = S[i - 1][j] + S[i][j - 1] - S[i - 1][j - 1] + a[i][j];
for (int i = 1; i <= MAXN + 1; ++i)
for (int j = 1; j <= MAXN + 1; ++j) {
x = i + r - 1, y = j + r - 1;
if (x > MAXN + 1 || y > MAXN + 1) continue;
Ans = max(Ans, S[x][y] - S[i - 1][y] - S[x][j - 1] + S[i - 1][j - 1]);
}
printf("%d\n", Ans);
return 0;
}
BZOJ1614 [Usaco2007 Jan]Telephone Lines架设电话线
二分求极值+最短路
二分边长,权值大于mid边权为1,小于或等于则为0。
跑一遍Dijkstra,看看最短路有没有到达mid,如果超过了,那么就满足题意。
经典好题
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
const int MAXN = 1000;
const int INF = 1000000;
using namespace std;
inline int read() {
int x = 0, w = 1; char c = ' ';
while (c < '0' || c > '9') {c = getchar(); if (c == '-') w = -1;}
while (c >= '0' && c <= '9') x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
return x * w;
}
struct Edge {
int to, w, nxt;
};
struct Node {
int id, num;
bool operator < (const Node &a) const {
return num > a.num;
}
Node(int _id, int _num) : id(_id), num(_num) {}
};
class Graph {
public :
Graph() {memset(head, -1, sizeof(head)), tot = 0, memset(dist, 0x3f, sizeof(dist)), memset(vis, false, sizeof(vis));}
void add(int u, int v, int w) {
edge[tot] = (Edge) {v, w, head[u]}, head[u] = tot++;
}
int Dijkstra(int s, int t);
private :
int head[MAXN + 5], tot, dist[MAXN + 5];
Edge edge[20000 + 5];
bool vis[MAXN + 5];
priority_queue < Node > Q;
};
int Graph::Dijkstra(int s, int t) {
Q.push(Node(s, 0)), dist[s] = 0;
while (!Q.empty()) {
Node u = Q.top(); Q.pop();
if (vis[u.id]) continue;
for (int i = head[u.id]; ~i; i = edge[i].nxt) {
int v = edge[i].to, w = edge[i].w;
if (u.num + w < dist[v]) {
dist[v] = w + u.num;
Q.push(Node(v, dist[v]));
}
}
vis[u.id] = true;
}
return dist[t];
}
struct Query {
int u, v, w;
}q[20000 + 5];
int n, m, k, Ans = -1;
bool check(int mid) {
Graph G;
for (int i = 1; i <= m; ++i) {
int u = q[i].u, v = q[i].v, w = q[i].w > mid;
G.add(u, v, w), G.add(v, u, w);
}
return G.Dijkstra(1, n) <= k;
}
int main() {
n = read(), m = read(), k = read();
for (int i = 1; i <= m; ++i) {
int u = read(), v = read(), w = read();
q[i] = (Query) {u, v, w};
}
int l = 0, r = INF;
while(l <= r) {
int mid = l + r >> 1;
if (check(mid))
r = mid - 1, Ans = mid;
else
l = mid + 1;
}
printf("%d\n", Ans);
return 0;
}