目录

noip模拟40

T1 送花

又又又挂分了……

直接把从每种颜色上上次出现的位置到上次出现的位置的区间减去当前颜色的价值,把从上次出现的位置+1到当前位置的区间加上当前颜色的价值就可以了

记得pushdown

注意pushup时是取最大值

最后直接查询第一个点的值就行

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
#include <bits/stdc++.h>
#define For(i, l, r) for (long long i = (l), i##end = (r); i <= i##end; ++i)
#define Fordown(i, r, l) for (long long i = (r), i##end = (l); i >= i##end; --i)
#define Set(a, v) memset(a, v, sizeof(a))
using namespace std;
const long long maxn = 1000010;

template<typename type>
type read() {
  type s = 0, f = 1;
  char ch = getchar();
  while (ch < '0' || ch > '9') {
    if (ch == '-') f = -1;
    ch = getchar();
  }
  while (ch >= '0' && ch <= '9') {
    s = s * 10 + ch - '0';
    ch = getchar();
  }
  return s * f;
}

long long max(long long a, long long b) {
  return (a > b) ? a : b;
}

class SEGT {
#define lid id << 1
#define rid id << 1 | 1
  struct TREE {
    long long l, r;
    long long lazy, val;
  } tree[maxn * 8];
  void down(long long id) {
    if (tree[id].lazy) {
      tree[lid].lazy += tree[id].lazy;
      tree[rid].lazy += tree[id].lazy;
      tree[lid].val += tree[id].lazy;
      tree[rid].val += tree[id].lazy;
      tree[id].lazy = 0;
    }
  }
public:
  void build(long long id, long long l, long long r) {
    tree[id].l = l;
    tree[id].r = r;
    if (l == r) return;
    long long mid = (l + r) / 2;
    build (lid, l, mid);
    build (rid, mid + 1, r);
  }
  void add(long long id, long long ql, long long qr, long long val) {
    long long l = tree[id].l, r = tree[id].r;
    if (ql > qr) return;
    if (ql == l && qr == r) {
      tree[id].val += val;
      tree[id].lazy += val;
      return;
    }
    down(id);
    long long mid = (l + r) / 2;
    if (qr <= mid) {
      add(lid, ql, qr, val);
    } else {
      if (ql > mid) {
        add(rid, ql, qr, val);
      } else {
        add(lid, ql, mid, val);
        add(rid, mid + 1, qr, val);
      }
    }
    tree[id].val = max(tree[lid].val, tree[rid].val);
  }
  long long query() {
    return tree[1].val;
  }
} tr;

long long col[maxn], w[maxn];
long long llst[maxn], lst[maxn];

long long n, m;
int main() {
  n = read<long long>();
  m = read<long long>();
  tr.build(1, 1, n);
  For(i, 1, n) {
    col[i] = read<long long>();
  }
  For(i, 1, m) {
    w[i] = read<long long>();
  }
  long long r = 1;
  long long maxx = 0;
  while (r <= n) {
    tr.add(1, llst[col[r]] + 1, lst[col[r]], -w[col[r]]);
    tr.add(1, lst[col[r]] + 1, r, w[col[r]]);
    llst[col[r]] = lst[col[r]];
    lst[col[r]] = r;
    // cout << tr.query() << endl;
    maxx = max(maxx, tr.query());
    r++;
  }
  cout << maxx << endl;
  return 0;
}

T2 星空

这个距离的定义非常奇怪,那我们就想如何让它变得不奇怪 .

.

.

.

旋转坐标系啊!

把坐标系转45度就变成了在两个的点的x坐标之差和y坐标之差中取最小值了,然后把距离为0的点用并查集缩起来,这样两点之间的距离就变成直接距离了(下面代码里加上2e5是为了把负的坐标变成正的)最后统计答案时把具有最小距离的点的并查集(不是把距离为0的点都缩起来了嘛)之间连边,答案就是边两边的并查集大小乘积(理解成配个对也行)

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
#include <bits/stdc++.h>
#define For(i, l, r) for (long long i = (l), i##end = (r); i <= i##end; ++i)
#define Fordown(i, r, l) for (long long i = (r), i##end = (l); i >= i##end; --i)
#define Set(a, v) memset(a, v, sizeof(a))
using namespace std;
const long long maxn = 100010;

template<typename type>
type read() {
  type s = 0, f = 1;
  char ch = getchar();
  while (ch < '0' || ch > '9') {
    if (ch == '-') f = -1;
    ch = getchar();
  }
  while (ch >= '0' && ch <= '9') {
    s = s * 10 + ch - '0';
    ch = getchar();
  }
  return s * f;
}

struct PNT {
  int x, y, id;
} p[maxn];

bool cmpx(PNT a, PNT b) {
  return a.x < b.x;
}
bool cmpy(PNT a, PNT b) {
  return a.y < b.y;
}

int getDis(PNT a, PNT b) {
  return min(abs(a.x - b.x), abs(a.y - b.y));
}

class DJU {
public:
  int fa[maxn], sz[maxn];
  void init(int n) {
    For(i, 1, n) {
      fa[i] = i;
      sz[i] = 1;
    }
  }
  int findFa(int a) {
    if (fa[a] != a) 
      return fa[a] = findFa(fa[a]);
    return a;
  }
  void merge(int a, int b) {
    int faa = findFa(a);
    int fab = findFa(b);
    if (faa != fab) {
      fa[fab] = faa;
      sz[faa] += sz[fab];
    }
  }
} dj; 

int bktx[400001], bkty[400001];

vector<pair<int, int> > e;

int n;
int main() {
  n = read<int>();
  dj.init(n);
  bool flg = 1;
  int lst = 0;
  For(i, 1, n) {
    p[i].x = read<int>();
    p[i].y = read<int>();
    p[i].id = i;
    int x = p[i].x, y = p[i].y;
    p[i].x = x - y;
    p[i].y = y + x;
  }
  For(i, 1, n) {
    if ((bktx[p[i].x + 200000] != 0) && (bkty[p[i].y + 200000] != 0)) {
      dj.merge(bktx[p[i].x + 200000], p[i].id);
      dj.merge(bktx[p[i].x + 200000], bkty[p[i].y + 200000]);
    } else {
      if (bktx[p[i].x + 200000] == 0) {
        bktx[p[i].x + 200000] = p[i].id;
      } else {
        dj.merge(bktx[p[i].x + 200000], p[i].id);
      }
      if (bkty[p[i].y + 200000] == 0) {
        bkty[p[i].y + 200000] = p[i].id;
      } else {
        dj.merge(bkty[p[i].y + 200000], p[i].id);
      }
    }
  }
  int ans = 0x3f3f3f3f;
  int cnt = 0;

  sort(p + 1, p + 1 + n, cmpx);
  For(i, 1, n - 1) {
    For(j, i + 1, n) {
      if (dj.findFa(p[i].id) != dj.findFa(p[j].id) && getDis(p[i], p[j]) != 0) {
        if (ans > getDis(p[i], p[j])) {
          ans = getDis(p[i], p[j]);
          e.clear();
          int pa, pb;
          pa = dj.findFa(p[i].id);
          pb = dj.findFa(p[j].id);
          if (pa > pb) swap(pa, pb);
          e.push_back(make_pair(pa, pb));
        } else {
          if (ans == getDis(p[i], p[j])) {
            int pa, pb;
            pa = dj.findFa(p[i].id);
            pb = dj.findFa(p[j].id);
            if (pa > pb) swap(pa, pb);
            e.push_back(make_pair(pa, pb));
          }
        }
        break;
      }
    }
  }
  
  sort(p + 1, p + 1 + n, cmpy);
  For(i, 1, n - 1) {
    For(j, i + 1, n) {
      if (dj.findFa(p[i].id) != dj.findFa(p[j].id) && getDis(p[i], p[j]) != 0) {
        if (ans > getDis(p[i], p[j])) {
          ans = getDis(p[i], p[j]);
          e.clear();
          int pa, pb;
          pa = dj.findFa(p[i].id);
          pb = dj.findFa(p[j].id);
          if (pa > pb) swap(pa, pb);
          e.push_back(make_pair(pa, pb));
        } else {
          if (ans == getDis(p[i], p[j])) {
            int pa, pb;
            pa = dj.findFa(p[i].id);
            pb = dj.findFa(p[j].id);
            if (pa > pb) swap(pa, pb);
            e.push_back(make_pair(pa, pb));
          }
        }
        break;
      }
    }
    }
  sort(e.begin(), e.end()); 
  vector<pair<int, int>>::iterator it = unique(e.begin(), e.end());
  e.erase(it, e.end());

  int ansbig = 0;
  for (auto i : e) {
    ansbig += dj.sz[i.first] * dj.sz[i.second];
  }
  cout << ans << endl;
  cout << ansbig << endl;
  return 0;
}

T3 零一串

没改过,不会