懒得吐槽了。
A
水的不能再水了。
B
题意:n个成环的点,有k个特殊点和其它每个点都有一条边。已知任意两个点之间最多1条边,边权是这两个点权值乘积,问所有边权之和。
分别处理特殊点和非特殊点统计一下就好了。
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <string>
#include <map>
#include <cstring>
#include <stack>
#include <queue>
#include <cmath>
#include <vector>
#include <set>
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
const int MAXN = 1e5 + 10;
const int INF = 1e9 + 10;
const int MOD = 110119;
void add(LL &x, LL y) { x += y; x %= MOD; }
int c[MAXN], a[MAXN];
bool vis[MAXN];
int main()
{
int n, k;
while(scanf("%d%d", &n, &k) != EOF) {
for(int i = 1; i <= n; i++) {
scanf("%d", &c[i]);
vis[i] = false;
}
LL sum2 = 0;
for(int i = 1; i <= k; i++) {
scanf("%d", &a[i]);
sum2 += c[a[i]];
vis[a[i]] = true;
}
LL ans = 0;
for(int i = 1; i <= n; i++) {
int next = i + 1;
if(next > n) {
next = 1;
}
if(vis[i]) continue;
if(!vis[next]) {
ans += 1LL * c[i] * sum2 + 1LL * c[i] * c[next];
}
else {
ans += 1LL * c[i] * sum2;
}
}
for(int i = 1; i <= n; i++) {
if(vis[i]) {
ans += 1LL * c[i] * (sum2 - c[i]);
sum2 -= c[i];
}
}
printf("%lld\n", ans);
}
return 0;
}
C
题意:一个汽车向x轴负向开,一个人从原点向(0,y)点走,给你这个汽车的形状(一个凸多边形),问你这个人最少需要多长时间可以到达目的地且不被车撞倒。
思路:考虑每个点x - v * t = d,d > 0,u * t = y。这样d = x - y / u * v。
我们统计一下最大的d和最小的d讨论一下即可。
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <string>
#include <map>
#include <cstring>
#include <stack>
#include <queue>
#include <cmath>
#include <vector>
#include <set>
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
const int MAXN = 1e6 + 10;
const int INF = 1e9 + 10;
const int MOD = 110119;
void add(LL &x, LL y) { x += y; x %= MOD; }
int main()
{
int n, w, u, v;
while(scanf("%d%d%d%d", &n, &w, &v, &u) != EOF) {
double Min = 2e9;
double Max = 0;
for(int i = 0; i < n; i++) {
int x, y; scanf("%d%d", &x, &y);
Min = min(Min, x * 1.0 - y * 1.0 / u * v);
Max = max(Max, x * 1.0 - y * 1.0 / u * v);
}
if(Min >= 0) {
printf("%.10lf\n", w * 1.0 / u);
}
else {
printf("%.10lf\n", Max / v + w * 1.0 / u);
}
}
return 0;
}
D
题意:问你区间里面出现偶数次的元素异或和。
ZZ,看错数据范围,直接莫队开搞,T了一发才发现多了一个0。浪费那么长时间才过,真的ZZ。
思路:转化问题,记区间出现不同元素异或和为sum1,区间元素异或和为sum2,那么结果显然为sum1 ^ sum2。我们只要快速求出区间不同元素异或和即可。
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <string>
#include <map>
#include <cstring>
#include <stack>
#include <queue>
#include <cmath>
#include <vector>
#include <set>
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
const int MAXN = 1e6 + 10;
const int INF = 1e9 + 10;
const int MOD = 110119;
void add(LL &x, LL y) { x += y; x %= MOD; }
struct Node {
int l, r, id;
};
Node num[MAXN];
bool cmp(Node a, Node b) {
return a.r < b.r;
}
LL C[MAXN];
map<int, int> lp;
int lowbit(int x) {
return x & (-x);
}
int n;
void add(int x, LL d) {
while(x <= n) {
C[x] ^= d;
x += lowbit(x);
}
}
LL Sum(int x) {
LL s = 0;
while(x > 0) {
s ^= C[x];
x -= lowbit(x);
}
return s;
}
LL a[MAXN], ans[MAXN], sum[MAXN];
int main()
{
while(scanf("%d", &n) != EOF) {
lp.clear(); sum[0] = 0;
for(int i = 1; i <= n; i++) {
scanf("%lld", &a[i]);
sum[i] = sum[i-1] ^ a[i];
}
int m; scanf("%d", &m);
for(int i = 1; i <= m; i++) {
scanf("%d%d", &num[i].l, &num[i].r);
num[i].id = i;
}
sort(num + 1, num + m + 1, cmp);
memset(C, 0, sizeof(C)); int j = 1;
for(int i = 1; i <= m; i++) {
while(j <= num[i].r) {
if(!lp[a[j]]) {
add(j, a[j]);
}
else {
add(lp[a[j]], a[j]);
add(j, a[j]);
}
lp[a[j]] = j; j++;
}
ans[num[i].id] = Sum(num[i].r) ^ Sum(num[i].l - 1) ^ sum[num[i].r] ^ sum[num[i].l-1];
}
for(int i = 1; i <= m; i++) {
printf("%lld\n", ans[i]);
}
}
return 0;
}