B. Inna and New Matrix of Candies
若果将题目中的all lines of the matrix where dwarf is not on the cell with candy改成
some lines of the matrix where dwarf is not on the cell with candy
即将all改成some应如何做???
D. Dima and Bacteria
题目有两种做法,并查集+floyd和搜索+floyd
搜索+floyd(判断时注意种类内可通过种类间来转移能量):
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <queue>
#include <vector>
#include <map>
#include <set>
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 100010;
int n, m, k;
vector<pair<int, int> >adj[maxn];
vector<int> type;
int dis[510][510];
int hash_to_type(int x)
{
int y = lower_bound(type.begin(), type.end(), x) - type.begin();
return y;
}
bool vis[maxn];
void floyd()
{
for (int r = 1; r <= k; r++)
for (int i = 1; i <= k; i++)
for (int j = 1; j <= k; j++)
{
if (i != j && dis[i][r] != INF && dis[r][j] != INF)
dis[i][j] = min(dis[i][j], dis[i][r] + dis[r][j]);
}
}
int main()
{
int x, y, cost;
scanf("%d%d%d", &n, &m, &k);
type.push_back(0);
for (int i = 1; i<= k; i++)
{
scanf("%d", &x);
type.push_back(x);
type[i] += type[i - 1];
}
sort(type.begin(), type.end());
for (int i = 1; i <= k; i++)
for (int j = 1; j <= k; j++)
{
if (i == j) dis[i][j] = 0;
else dis[i][j] = INF;
}
for (int i = 0; i < m; i++)
{
scanf("%d%d%d",&x,&y, &cost);
adj[x].push_back(make_pair(y, cost));
adj[y].push_back(make_pair(x, cost));
int type_x = hash_to_type(x);
int type_y = hash_to_type(y);
if (dis[type_x][type_y] > cost)
dis[type_x][type_y] = dis[type_y][type_x] = cost;
}
floyd();
set<int>s;
for (int i = 1; i <= k; i++)
for (int j = i + 1; j <= k; j++)
if (dis[i][j] == 0) s.insert(i), s.insert(j);
int fla = 0;
for (int i = 1; i <= k; i++)
{
if (s.find(i) != s.end()) continue;
memset(vis, 0, sizeof(vis));
queue<int>q;
while (!q.empty()) q.pop();
vis[type[i - 1] + 1] = 1;
q.push(type[i - 1] + 1);
int tot = 1;
while (!q.empty())
{
int x = q.front(); q.pop();
for (int j = 0; j < adj[x].size(); j++)
{
pair<int, int> pi;
pi = adj[x][j];
if (pi.first > type[i - 1] && pi.first <= type[i] && pi.second == 0 && !vis[pi.first])
{
q.push(pi.first);
vis[pi.first] = 1;
tot++;
}
}
}
if (tot != type[i] - type[i - 1])
{
fla = 1; break;
}
}
if (fla) printf("No\n");
else
{
printf("Yes\n");
for (int i = 1; i <= k; i++)
{
for (int j = 1; j <= k; j++)
{
if (dis[i][j] == INF) printf("-1");
else printf("%d", dis[i][j]);
if (j == k) printf("\n");
else printf(" ");
}
}
}
}
int hash_to_type(int x)
{
int y = lower_bound(type.begin(), type.end(), x) - type.begin();
return y;
}///
type.push_back(0);
for (int i = 1; i<= k; i++)
{
scanf("%d", &x);
type.push_back(x);
type[i] += type[i - 1];
}
sort(type.begin(), type.end());///
for (int i = 0; i < m; i++)
{
scanf("%d%d%d",&x,&y, &cost);
adj[x].push_back(make_pair(y, cost));
adj[y].push_back(make_pair(x, cost));
int type_x = hash_to_type(x);///
int type_y = hash_to_type(y);///
if (dis[type_x][type_y] > cost)
dis[type_x][type_y] = dis[type_y][type_x] = cost;
}
线段树和set 两中做法
线段树的做法:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <cstdlib>
#include <fstream>
#include <vector>
#include <set>
using namespace std;
typedef long long LL;
const int INF = 0x3f3f3f3f;
const int maxn = 100010;
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
#define ll rt << 1
#define rr rt << 1 | 1
int n, m;
int a[maxn];
struct SegTree{
LL ret[maxn<<2];
int pre[maxn<<2], suf[maxn<<2];
void up(int l, int r, int m, int rt)
{
pre[rt] = pre[ll];
suf[rt] = suf[rr];
if (pre[ll] == (m - l + 1)) pre[rt] += pre[rr];///(r - l + 2) / 2
if (suf[rr] == (r - m)) suf[rt] += suf[ll];///(r - l + 1) / 2
ret[rt] = ret[ll] + ret[rr];
if (suf[ll] && pre[rr])
ret[rt] += 1LL * suf[ll] * pre[rr];
}
void build(int l, int r, int rt, int p)
{
if (l == r)
{
ret[rt] = pre[rt] = suf[rt] = (a[l] & (1 << p)) == 0 ? 0 : 1;
return ;
}
int m = (l + r) >> 1;
build(lson, p);
build(rson, p);
up(l, r, m, rt);
}
void update(int x, int val, int l, int r, int rt)
{
if (l == r)
{
ret[rt] = pre[rt] = suf[rt] = val;
return ;
}
int m = (l + r) >> 1;
if (x <= m) update(x, val, lson);
else update(x, val, rson);
up(l, r, m, rt);
}
}sg[20];
int main()
{
cin >> n >> m;
for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
for (int p = 0; p <= 18; p++)
{
sg[p].build(1, n, 1, p);
}
while (m--)
{
int id, v;
LL ans = 0;
scanf("%d%d", &id, &v);
for (int p = 0; p <= 18; p++)
{
sg[p].update(id, (v & (1 << p)) == 0 ? 0 : 1, 1, n, 1);
ans += 1LL * sg[p].ret[1] * (1 << p);
}
cout << ans << endl;
}
}
set做法:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <cstdlib>
#include <fstream>
#include <vector>
#include <set>
using namespace std;
typedef long long LL;
const int INF = 0x3f3f3f3f;
const int maxn = 100010;
int n, m;
int a[maxn];
set<int>s[20];
set<int>::iterator it, pre, next;
LL ans;
int main()
{
cin >> n >> m;
ans = 0;
int now;
for (int i = 1; i <= n; i++) scanf("%d",&a[i]);
for (int j = 0; j <= 18; j++)
{
s[j].insert(0);
s[j].insert(n + 1);
now = 0;
for (int i = 1; i <= n; i++)
{
if (a[i] & (1 << j)) ans += 1LL * (i - now) * (1 << j);
else s[j].insert(i), now = i;
}
}
while (m--)
{
int id, v;
scanf("%d%d", &id, &v);
for (int p = 0; p <= 18; p++)
{
if ( (a[id] & (1 << p)) == (v & (1 << p)) ) continue;
else if (a[id] & (1 << p))
{
it = s[p].lower_bound(id);
next = it;
it--;
pre = it;
ans -= 1LL * ((*next) - id) * (id - (*pre)) * (1 << p);
s[p].insert(id);
}
else
{
it = s[p].find(id);
next = s[p].upper_bound(id);
it--;
pre = it;
ans += 1LL * ((*next) - id) * (id - (*pre)) * (1 << p);
s[p].erase(id);
}
}
a[id] = v;
cout << ans << endl;
}
}