1001 Alisha’s Party
题意: m个 t p 二元组对 表示t-th来到门前 放p个人进来 按照权值从大到小放 最终还要再开一次门把所有人放进来分析: 优先队列或者set模拟 然后注意二元组要先排序。。。 赛上因为这个wa了好几发
代码:
//
// Created by TaoSama on 2015-09-13
// Copyright (c) 2015 TaoSama. All rights reserved.
//
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <set>
#include <vector>
using namespace std;
#define pr(x) cout << #x << " = " << x << " "
#define prln(x) cout << #x << " = " << x << endl
const int N = 1.5e5 + 10, INF = 0x3f3f3f3f, MOD = 1e9 + 7;
int n, m, q;
char name[N][205];
int val[N];
struct Query {
int t, p;
Query() {}
Query(int t, int p): t(t), p(p) {}
bool operator< (const Query& rhs) const {
return t < rhs.t;
}
} A[N];
int Q[N];
bool vis[N];
int ans[N];
void solve(int Max) {
set<pair<int, int> > s;
int rnk = 0, j = 1;
for(int i = 1; i <= m; ++i) {
for(; j <= A[i].t; ++j)
s.insert(make_pair(val[j], -j));
for(int k = 1; k <= A[i].p; ++k) {
if(s.empty()) break;
auto iter = s.end(); --iter;
if(vis[++rnk]) {
ans[rnk] = -iter->second;
// printf("%d\n", -iter->second);
}
if(rnk == Max) return;
s.erase(iter);
}
}
for(; j <= n; ++j) s.insert(make_pair(val[j], -j));
while(s.size()) {
auto iter = s.end(); --iter;
if(vis[++rnk]) {
ans[rnk] = -iter->second;
// printf("%d\n", -iter->second);
}
if(rnk == Max) return;
s.erase(iter);
}
}
int main() {
#ifdef LOCAL
freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
#endif
ios_base::sync_with_stdio(0);
int t; scanf("%d", &t);
while(t--) {
scanf("%d%d%d", &n, &m, &q);
for(int i = 1; i <= n; ++i)
scanf("%s%d", name[i], val + i);
for(int i = 1; i <= m; ++i) {
int x, y; scanf("%d%d", &x, &y);
A[i] = Query(x, y);
}
sort(A + 1, A + 1 + m);
int Max = 0;
memset(vis, false, sizeof vis);
for(int i = 1; i <= q; ++i) {
scanf("%d", Q + i);
vis[Q[i]] = true;
Max = max(Max, Q[i]);
}
solve(Max);
for(int i = 1; i <= q; ++i)
printf("%s%c", name[ans[Q[i]]], " \n"[i == q]);
}
return 0;
}
1002 Ponds
题意: 不断删去度小于2的点 求剩余图中 连通分量里点的个数为奇数的 总权和
分析: 搞个队列乱搞就行了 注意push的时候 判断vis 不然会MLE
代码:
//
// Created by TaoSama on 2015-09-13
// Copyright (c) 2015 TaoSama. All rights reserved.
//
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <set>
#include <vector>
using namespace std;
#define pr(x) cout << #x << " = " << x << " "
#define prln(x) cout << #x << " = " << x << endl
const int N = 1e4 + 10, INF = 0x3f3f3f3f, MOD = 1e9 + 7;
const int M = 1e5 + 10;
int n, m;
int deg[N], val[N];
vector<int> G[N];
bool vis[N];
void dfs(int u, int &cnt, long long& sum) {
sum += val[u];
++cnt;
vis[u] = true;
for(int i = 0; i < G[u].size(); ++i) {
int v = G[u][i];
if(vis[v]) continue;
dfs(v, cnt, sum);
}
}
int main() {
#ifdef LOCAL
freopen("in.txt", "r", stdin);
// freopen("out.txt","w",stdout);
#endif
ios_base::sync_with_stdio(0);
int t; scanf("%d", &t);
while(t--) {
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; ++i) {
scanf("%d", val + i);
G[i].clear();
vis[i] = false;
deg[i] = 0;
}
for(int i = 1; i <= m; ++i) {
int u, v; scanf("%d%d", &u, &v);
G[u].push_back(v);
G[v].push_back(u);
++deg[u], ++deg[v];
}
queue<int> q;
for(int i = 1; i <= n; ++i)
if(deg[i] < 2) q.push(i);
while(q.size()) {
int u = q.front(); q.pop();
deg[u] = 0; vis[u] = true;
for(int i = 0; i < G[u].size(); ++i) {
int v = G[u][i];
if(--deg[v] < 2 && !vis[v]) q.push(v);
}
}
long long ans = 0;
for(int i = 1; i <= n; ++i) {
if(vis[i]) continue;
int cnt = 0; long long sum = 0;
dfs(i, cnt, sum);
if(cnt & 1) ans += sum;
}
printf("%I64d\n", ans);
}
return 0;
}
1005 Travel
题意: 就是求q次询问 对于所有路径每条边权不超过d 的(s,t)起终点二元组的个数分析: 离线询问 然后并查集 其实就是求连通分量里点的个数 然后求个C_n_2 (a,b) (b,a)算不同的 不除就行了
赛上因为没有按秩合并就莫名跪了好多发 至今不知道为啥
代码:
//
// Created by TaoSama on 2015-09-13
// Copyright (c) 2015 TaoSama. All rights reserved.
//
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <set>
#include <vector>
using namespace std;
#define pr(x) cout << #x << " = " << x << " "
#define prln(x) cout << #x << " = " << x << endl
const int N = 2e4 + 10, INF = 0x3f3f3f3f, MOD = 1e9 + 7;
const int M = 1e5 + 10;
int n, m, q;
long long ans[5005];
struct Edge {
int u, v, c;
Edge() {}
Edge(int u, int v, int c) : u(u), v(v), c(c) {}
bool operator< (const Edge& rhs) const {
return c < rhs.c;
}
} G[M];
struct Query {
int d, id;
Query() {}
Query(int d, int id): d(d), id(id) {}
bool operator< (const Query& rhs) const {
return d < rhs.d;
}
} Q[5005];
long long now;
int par[N], rnk[N], num[N];
int find(int x) {
return par[x] == x ? x : find(par[x]);
}
void unite(int x, int y) {
x = find(x); y = find(y);
if(x == y) return;
now += num[x] * num[y];
if(rnk[x] < rnk[y]) {
par[x] = y;
num[y] += num[x]; num[x] = 0;
} else {
par[y] = x;
if(rnk[x] == rnk[y]) ++rnk[x];
num[x] += num[y]; num[y] = 0;
}
}
int main() {
#ifdef LOCAL
freopen("in.txt", "r", stdin);
// freopen("out.txt","w",stdout);
#endif
ios_base::sync_with_stdio(0);
int t; scanf("%d", &t);
while(t--) {
scanf("%d%d%d", &n, &m, &q);
for(int i = 0; i < m; ++i) {
int u, v, c; scanf("%d%d%d", &u, &v, &c);
G[i] = Edge(u, v, c);
}
sort(G, G + m);
for(int i = 0; i < q; ++i) {
int x; scanf("%d", &x);
Q[i] = Query(x, i);
}
sort(Q, Q + q);
for(int i = 1; i <= n; ++i) {
par[i] = i;
rnk[i] = 0;
num[i] = 1;
}
memset(ans, 0, sizeof ans);
now = 0;
for(int i = 0, j = 0; i < q; ++i) {
int cur = Q[i].d;
while(j < m) {
Edge &e = G[j];
if(e.c <= cur) {
unite(e.u, e.v);
} else break;
++j;
}
ans[Q[i].id] = now;
}
for(int i = 0; i < q; ++i) printf("%I64d\n", ans[i] * 2);
}
return 0;
}
1007 The Water Problem
题意: 区间RMQ裸题分析: 线段树或者ST都行
代码:
//
// Created by TaoSama on 2015-09-13
// Copyright (c) 2015 TaoSama. All rights reserved.
//
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <set>
#include <vector>
using namespace std;
#define pr(x) cout << #x << " = " << x << " "
#define prln(x) cout << #x << " = " << x << endl
const int N = 1e3 + 10, INF = 0x3f3f3f3f, MOD = 1e9 + 7;
int n, q, dp[2][N][20];
int RMQ(int l, int r) {
int k = 31 - __builtin_clz(r - l + 1);
int Max = max(dp[1][l][k], dp[1][r - (1 << k) + 1][k]);
// int Min = min(dp[0][l][k], dp[0][r - (1 << k) + 1][k]);
return Max;
}
int main() {
#ifdef LOCAL
freopen("in.txt", "r", stdin);
// freopen("out.txt","w",stdout);
#endif
ios_base::sync_with_stdio(0);
int t; scanf("%d", &t);
while(t--) {
scanf("%d", &n);
for(int i = 1; i <= n; ++i) {
scanf("%d", &dp[0][i][0]);
dp[1][i][0] = dp[0][i][0];
}
for(int j = 1; (1 << j) <= n; ++j) {
for(int i = 1; i + (1 << j) - 1 <= n; ++i) {
dp[0][i][j] = min(dp[0][i][j - 1],
dp[0][i + (1 << j - 1)][j - 1]);
dp[1][i][j] = max(dp[1][i][j - 1],
dp[1][i + (1 << j - 1)][j - 1]);
}
}
scanf("%d", &q);
while(q--) {
int x, y; scanf("%d%d", &x, &y);
printf("%d\n", RMQ(x, y));
}
}
return 0;
}
1008 Elven Postman
题意: 构建二叉搜索树 然后搜出特定点的路径分析: - - 构建二叉树的只是 还是很简单的 O(n^2)可过 集训队里有一个O(nlogn)的建树办法 曾经有过一道10^5数据的题 被下面这个n^2的水过去了
代码:
//
// Created by TaoSama on 2015-09-13
// Copyright (c) 2015 TaoSama. All rights reserved.
//
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <set>
#include <vector>
using namespace std;
#define pr(x) cout << #x << " = " << x << " "
#define prln(x) cout << #x << " = " << x << endl
const int N = 1e3 + 10, INF = 0x3f3f3f3f, MOD = 1e9 + 7;
int n, q;
int sz, ls[N], rs[N], val[N];
int newNode(int x) {
++sz;
ls[sz] = rs[sz] = 0;
val[sz] = x;
return sz;
}
int insert(int rt, int x) {
if(!val[rt]) return newNode(x);
if(x < val[rt]) ls[rt] = insert(ls[rt], x);
else rs[rt] = insert(rs[rt], x);
return rt;
}
void dfs(int rt, int x) {
if(x < val[rt]) {
putchar('E');
dfs(ls[rt], x);
} else if(x > val[rt]) {
putchar('W');
dfs(rs[rt], x);
}
}
int main() {
#ifdef LOCAL
freopen("in.txt", "r", stdin);
// freopen("out.txt","w",stdout);
#endif
ios_base::sync_with_stdio(0);
int t; scanf("%d", &t);
while(t--) {
scanf("%d", &n);
sz = 0; memset(val, 0, sizeof val);
for(int i = 1; i <= n; ++i) {
int x; scanf("%d", &x);
insert(1, x);
}
scanf("%d", &q);
while(q--) {
int x; scanf("%d", &x);
dfs(1, x);
puts("");
}
}
return 0;
}
1010 Unknown Treasure
题意: 求解大组合数对多个质数乘积取模分析: Lucas + CRT模版题 注意CRT合并的时候会炸longlong 需要模拟LL*LL的乘法
代码: 队友写的我贴个板子
//
// Created by TaoSama on 2015-09-13
// Copyright (c) 2015 TaoSama. All rights reserved.
//
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <set>
#include <vector>
using namespace std;
#define pr(x) cout << #x << " = " << x << " "
#define prln(x) cout << #x << " = " << x << endl
const int N = 1e5 + 10, INF = 0x3f3f3f3f, MOD = 1e9 + 7;
const int M = 1e5 + 10;
typedef long long ll;
ll n, m, k;
ll a[12], mm[12];
ll quick_mod(ll a, ll b, ll p) {
ll ans = 1;
a %= p;
while(b) {
if(b & 1) ans = ans * a % p;
b >>= 1;
a = a * a % p;
}
return ans;
}
ll C(ll n, ll m, ll p) {
if(m > n) return 0;
ll ans = 1;
for(int i = 1; i <= m; i++) {
ll a = (n + i - m) % p;
ll b = i % p;
ans = ans * (a * quick_mod(b, p - 2, p) % p) % p;
}
return ans;
}
ll Lucas(ll n, ll m, ll p) {
if(m == 0) return 1;
return C(n % p, m % p, p) * Lucas(n / p, m / p, p) % p;
}
ll Extended_Euclid(ll a, ll b, ll &x, ll &y) {
ll d;
if(b == 0) {
x = 1; y = 0;
return a;
}
d = Extended_Euclid(b, a % b, y, x);
y -= a / b * x;
return d;
}
ll mod_mul(ll a, ll b, ll mod) {
ll ret = 0;
while(b) {
if(b & 1) ret = (ret + a) % mod;
a = (a + a) % mod;
b >>= 1;
}
return ret;
}
ll CRT() {
ll d, x, y, tmp, M, ret;
ret = 0;
M = 1;
for(int i = 0; i < k; i++)
M *= mm[i];
for(int i = 0; i < k; i++) {
tmp = M / mm[i];
d = Extended_Euclid(mm[i], tmp, x, y);
ll temp = mod_mul(y, tmp, M);
temp = mod_mul(temp, a[i], M);
ret = (ret + temp) % M;
//ret=(ret+y*tmp*a[i])%M;
}
return (M + ret) % M;
}
int main() {
#ifdef LOCAL
freopen("in.txt", "r", stdin);
// freopen("out.txt","w",stdout);
#endif
ios_base::sync_with_stdio(0);
int T; cin >> T;
while(T--) {
cin >> n >> m >> k;
for(int i = 0; i < k; i++) {
cin >> mm[i];
a[i] = Lucas(n, m, mm[i]);
}
cout << CRT() << endl;
}
return 0;
}