今天的题目有些难
一看是非常的可做
32分直接 O ( n 2 ) O(n^2) O(n2)连边跑 d i j k s t r a dijkstra dijkstra
再来20分,使用二分查找对应点,然后连边,跑 d i j k s t r a dijkstra dijkstra
再来20分,我就不会啦,应该是线段树优化建边,我没学过,所以我在线学习了一下,然后是疯狂调试,看起来是过了……
满分的应该是想不出来的
Code:
#include
#define maxn 100010
using namespace std;
struct Edge{
int to, next, len;
}edge[maxn << 1];
struct POS{
int x, y, id;
}pos[maxn];
struct node{
int val, len;
bool operator < (const node &x) const{ return x.len < len; }
};
priority_queue <node> q;
int num, head[maxn], n, m, W, H, cnt;
int dis[maxn << 4], vis[maxn << 4];
int pp1[maxn], pp2[maxn];
struct Seg{
int l, r, num;
}seg[5][maxn << 2];
struct Vec{
int v, w;
};
vector <Vec> G[maxn << 4];
inline int read(){
int s = 0, w = 1;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') w = -1;
for (; isdigit(c); c = getchar()) s = (s << 1) + (s << 3) + (c ^ 48);
return s * w;
}
void addedge(int x, int y, int z){ edge[++num] = (Edge){ y, head[x], z }; head[x] = num; }
void dijkstra(){
dis[1] = 0;
for (int i = 2; i <= n; ++i) dis[i] = 1e9;
q.push((node) { 1, 0 });
while (!q.empty()){
node tmp = q.top(); q.pop();
int u = tmp.val, len = tmp.len;
if (vis[u]) continue;
vis[u] = 1;
for (int i = head[u]; i; i = edge[i].next){
int v = edge[i].to;
if (dis[v] > len + edge[i].len){
dis[v] = len + edge[i].len;
if (!vis[v]) q.push( (node) { v, dis[v] });
}
}
}
for (int i = 2; i <= n; ++i) printf("%d\n", dis[i]);
}
void do1(){
for (int i = 1; i <= m; ++i){
int p = read(), t = read(), l = read(), r = read(), d = read(), u = read();
for (int j = 1; j <= n; ++j)
if (p != j && pos[j].x >= l && pos[j].x <= r && pos[j].y >= d && pos[j].y <= u)
addedge(p, j, t);
}
dijkstra();
}
#define ls rt << 1
#define rs rt << 1 | 1
typedef pair<int, int> pii;
void build(int rt, int l, int r, int op){
seg[op][rt].l = l, seg[op][rt].r = r, seg[op][rt].num = ++cnt;
if (l == r){
if (op == 1) pp1[l] = cnt; else{
pp2[l] = cnt;
G[pp2[l]].push_back( (Vec) { pp1[l], 0} );
}
return;
}
int mid = (l + r) >> 1;
build(ls, l, mid, op); build(rs, mid + 1, r, op);
if (op == 1){
G[seg[op][ls].num].push_back( (Vec){seg[op][rt].num, 0} );
G[seg[op][rs].num].push_back( (Vec){seg[op][rt].num, 0} );
} else{
G[seg[op][rt].num].push_back( (Vec){seg[op][ls].num, 0} );
G[seg[op][rt].num].push_back( (Vec){seg[op][rs].num, 0} );
}
}
void update(int rt, int l, int r, int u, int w, int op){
if(seg[op][rt].l == l && seg[op][rt].r == r) {
if (op == 1) G[u].push_back( (Vec){seg[2][rt].num, w} ); else
G[seg[1][rt].num].push_back( (Vec){u, w} );
return;
}
int mid = (seg[op][rt].l + seg[op][rt].r) >> 1;
if (r <= mid) update(ls, l, r, u, w, op); else
if (l > mid) update(rs, l, r, u, w, op); else {
update(ls, l, mid, u, w, op);
update(rs, mid + 1, r, u, w, op);
}
}
void do2_dijkstra(int s) {
for (int i = 1; i <= cnt; ++i) dis[i] = 1e9;
dis[pp1[s]] = 0;
priority_queue<pii, vector<pii>, greater<pii> > q;
q.push( (pii){0, pp1[s]} );
while (!q.empty()) {
int u = q.top().second; q.pop();
if (vis[u]) continue;
vis[u] = 1;
int v;
for (int i = 0; i < (int) G[u].size(); ++i) {
v = G[u][i].v;
if (dis[v] > dis[u] + G[u][i].w) {
dis[v] = dis[u] + G[u][i].w;
q.push( (pii){dis[v], v} );
}
}
}
}
void do2(){
build(1, 1, W, 1); build(1, 1, W, 2);
for (int i = 1; i <= m; ++i){
int p = read(), t = read(), l = read(), r = read(), d = read(), u = read();
update(1, l, r, pp1[pos[p].x], t, 1);
}
do2_dijkstra(pos[1].x);
for (int i = 2; i <= n; ++i) printf("%d\n", min(dis[pp1[pos[i].x]], dis[pp2[pos[i].x]]));
}
bool do3_cmp(POS a, POS b){ return a.x == b.x ? a.y < b.y : a.x < b.x; }
void do3(){
for (int i = 1; i <= n; ++i) pos[i].id = i;
sort(pos + 1, pos + 1 + n, do3_cmp);
for (int i = 1; i <= m; ++i){
int p = read(), t = read(), l = read(), r = read(), d = read(), u = read();
int ll = 1, rr = n, q = 0;
while (ll <= rr){
int mid = (ll + rr) >> 1;
if (pos[mid].x < l || pos[mid].x == l && pos[mid].y < d) ll = mid + 1; else
rr = mid - 1, q = mid;
}
addedge(p, pos[q].id, t);
}
dijkstra();
}
int main(){
freopen("jump.in", "r", stdin);
freopen("jump.out", "w", stdout);
n = read(), m = read(), W = read(), H = read();
for (int i = 1; i <= n; ++i) pos[i].x = read(), pos[i].y = read();
if (n <= 100) do1(); else
if (H == 1) do2(); else do3();
return 0;
}
T1写了3.5h,后面的题目没时间写了,T2一看,没什么思路,直接上dfs拿10分
Code:
#include
#define maxn 110
#define qy 998244353
#define int long long
using namespace std;
int ans[maxn], lena, lenb, a[maxn], b[maxn], f[maxn], A[maxn], n, m, type;
inline int read(){
int s = 0, w = 1;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') w = -1;
for (; isdigit(c); c = getchar()) s = (s << 1) + (s << 3) + (c ^ 48);
return s * w;
}
int ksm(int n, int k){
if (!k) return 1;
int sum = ksm(n, k >> 1);
sum = 1LL * sum * sum % qy;
if (k & 1) sum = 1LL * sum * n % qy;
return sum;
}
void dfs(int i, int j, int p){
int inv = ksm(i + j, qy - 2);
(ans[i + j] += a[i] * i % qy * inv % qy * p % qy) %= qy;
(ans[i + j] += b[j] * j % qy * inv % qy * p % qy) %= qy;
if (i) dfs(i - 1, j, p * i % qy * inv % qy);
if (j) dfs(i, j - 1, p * j % qy * inv % qy);
}
signed main(){
freopen("landlords.in", "r", stdin);
freopen("landlords.out", "w", stdout);
n = read(), m = read(), type = read();
for (int i = 1; i <= n; ++i) f[i] = type == 1 ? i : i * i;
for (int i = 1; i <= m; ++i) A[i] = read();
for (int i = 1; i <= A[1]; ++i) a[i] = f[i];
for (int i = A[1] + 1; i <= n; ++i) b[i - A[1]] = f[i];
lena = A[1], lenb = n - lena;
dfs(lena, lenb, 1);
int M = read();
while (M--){
int x = read();
printf("%lld\n", ans[x]);
}
return 0;
}
交互题什么的我完全不会了。。。
我不知道他是怎么操作的
所以这道题我直接弃疗了
所以期望得分72+10+0=82吧
如果能达到,两天加起来刚好200.。。。
感觉不错