2018-2019 ICPC Southeastern European Regional Programming Contest (SEERC 2018)
有点难的一场。
题目链接:http://codeforces.com/gym/101964
B:
solver:czq
#!/usr/bin/env python
num = list(map(int, input().split()))
a, b, c, n = num[0], num[1], num[2], num[3]
mod = 2 ** 64
if n % 2 == 0:
ans = n * (n + 8) * (n - 2) // 24 % mod
else:
ans = n * (n + 1) * (n - 1) // 24 % mod
if a != b and a != c and b != c:
ans = ans * 6 % mod
elif a != b or a != c or b != c:
ans = ans * 3 % mod
print(ans)
C:
solver: czq、zyh
/* basic header */
#include <bits/stdc++.h>
/* define */
#define ll long long
#define pb emplace_back
#define mp make_pair
#define eps 1e-8
#define lson (curpos<<1)
#define rson (curpos<<1|1)
/* namespace */
using namespace std;
/* header end */
const int MAXN = 1100;
int n, m, color[MAXN], vis[MAXN];
vector<int>g[MAXN];
int main() {
scanf("%d%d", &n, &m);
for (int i = 0; i <= n; i++) g[i].clear();
for (int i = 1; i <= n; i++) scanf("%d", &color[i]);
for (int u, v, i = 0; i < n - 1; i++) {
scanf("%d%d", &u, &v);
g[u].pb(v), g[v].pb(u);
}
function<int(int, int, int, int)> dfs = [&](int cur, int fa, int depth, int maxDepth)->int{
int sum = color[cur];
if (depth >= maxDepth) return sum;
for (auto v : g[cur]) {
if (!vis[v] || v == fa) continue;
sum += dfs(v, cur, depth + 1, maxDepth);
}
return sum;
};
function<int(int)> check = [&](int maxDepth)->int{
memset(vis, 0, sizeof vis);
queue<int>q;
while (q.size()) q.pop();
q.push(1);
vis[1] = 1;
while (q.size()) {
int u = q.front();
q.pop();
vis[u] = 1;
if (dfs(u, 0, 0, maxDepth) >= m) return 1;
for (auto v : g[u]) {
if (!vis[v]) q.push(v);
}
}
return 0;
};
int l = 0, r = n;
while (l < r) {
int mid = l + r >> 1;
if (check(mid)) r = mid;
else l = mid + 1;
}
printf("%d\n", r);
return 0;
}
E:
solver:czq
/* basic header */
#include <bits/stdc++.h>
/* define */
#define ll long long
#define pb emplace_back
#define mp make_pair
#define eps 1e-8
#define lson (curpos<<1)
#define rson (curpos<<1|1)
/* namespace */
using namespace std;
/* header end */
const int MAXN = 1e6 + 10;
struct Fish {
int x, y, leftMost, rightMost;
Fish() {}
};
int coor[MAXN], maxRightMost = 0;
int main() {
int n, m, l;
scanf("%d%d%d", &n, &m, &l);
vector<Fish> fishs(n);
vector<int> num;
vector<int> fishers(m);
for (auto &fish : fishs) {
scanf("%d%d", &fish.x, &fish.y);
if (fish.y > l) continue;
int maxDeltaX = l - fish.y;
int leftMost = max(0, fish.x - maxDeltaX), rightMost = fish.x + maxDeltaX;
num.push_back(leftMost), num.push_back(rightMost + 1);
fish.leftMost = leftMost, fish.rightMost = rightMost + 1;
maxRightMost = max(maxRightMost, rightMost + 1);
}
for (auto &fisher : fishers) {
scanf("%d", &fisher);
maxRightMost = max(fisher, maxRightMost);
num.push_back(fisher);
}
sort(num.begin(), num.end());
num.erase(unique(num.begin(), num.end()), num.end());
maxRightMost = lower_bound(num.begin(), num.end(), maxRightMost) - num.begin();
for (auto fish : fishs) {
if (fish.y > l) continue;
coor[lower_bound(num.begin(), num.end(), fish.leftMost) - num.begin()]++;
coor[lower_bound(num.begin(), num.end(), fish.rightMost) - num.begin()]--;
}
int temp = 0;
for (int i = 0; i <= maxRightMost; i++) {
coor[i] += temp;
temp = coor[i];
}
for (auto fisher : fishers)
printf("%d\n", coor[lower_bound(num.begin(), num.end(), fisher) - num.begin()]);
return 0;
}
G:
solver:czq、zyh
好题。构造几组数据发现答案基本都是4k+1
的形式,再开两棵线段树维护相邻行和列颜色数量即可
/* basic header */
#include <bits/stdc++.h>
/* define */
#define ll long long
#define pb emplace_back
#define mp make_pair
#define eps 1e-8
#define lson (curpos<<1)
#define rson (curpos<<1|1)
/* namespace */
using namespace std;
/* header end */
const int MAXN = (1 << 20) + 1;
ll totalMatrix = 0, segT[2][MAXN << 2], state[2][21];
int n, m, _size;
void update(int id, int pos, int curpos, int curl, int curr, int depth) {
if (curl == curr) {
segT[id][curpos] ^= 1;
return;
}
int mid = curl + curr >> 1;
if (pos <= mid) update(id, pos, lson, curl, mid, depth + 1);
else update(id, pos, rson, mid + 1, curr, depth + 1);
if (segT[id][curpos] != -1) state[id][depth]--;
if (segT[id][lson] == segT[id][rson]) segT[id][curpos] = segT[id][lson];
else segT[id][curpos] = -1;
if (segT[id][curpos] != -1) state[id][depth]++;
}
struct FastIO {
static const int LEN=1<<18|1;
char buf[LEN],wbuf[LEN];
int s=0,t=0,wpos=0;
inline int read(){
int res=((s==t)&&(t=(s=0)+fread(buf,1,LEN,stdin)),s==t?-1:buf[s++]);
// 注意,是读取到文件末尾时立刻退出程序
if(res==-1) exit(0);
return res;
}
inline void out(int x){
wpos==LEN?fwrite(wbuf,1,LEN,stdout),wbuf[0]=x,wpos=1:wbuf[wpos++]=x;
}
// 有符号:
inline int rint(){
// 根据读入是int还是long long决定x的类型
int c=read(),x=0,s=1;
if(c==-1)return 0;
while(c<=32)c=read();
if(c=='-')s=-1,c=read();
while(isdigit(c))x=x*10+c-'0',c=read();
return x*s;
}
inline int ruint(){
int c=read(),x=0;
while(c<=32)c=read();
while(isdigit(c))x=x*10+c-'0',c=read();
return x;
}
inline void rstr(char *str){
int c=read();
while(c<=32)c=read();
while(c>32)*str++=c,c=read();
*str=0;
}
// 根据类型
inline void wint(long long x){
// 如果含有负数,取消注释
// if(x<0)wchar('-'),x=-x;
char str[24];int n=0;
while(x||!n)str[n++]='0'+x%10,x/=10;
while(n--)out(str[n]);
}
inline void wchar(char str){
out(str);
}
inline void wstr(const char *s){
while(*s)out(*s++);
}
inline void over(){
if(wpos)fwrite(wbuf,1,wpos,stdout),wpos=0;
}
~FastIO(){
if(wpos)fwrite(wbuf,1,wpos,stdout),wpos=0;
}
}io;
int main() {
_size=io.rint();
m=io.rint();
//read(_size); read(m);
n = (1 << _size);
for (int i = 0; i < _size; i++) {
state[0][i + 1] = state[1][i + 1] = (1 << i);
totalMatrix += (1LL << (i << 1));
}
for (int i = 0; i < m; i++) {
int id, x; //read(id); read(x);
id=io.rint();
x=io.rint();
update(id, x, 1, 1, n, 1);
ll tmp = 0;
for (int i = 1; i <= _size; i++)
tmp += state[0][i] * state[1][i];
io.wint(4ll * (totalMatrix - tmp) + 1ll);
io.wchar('\n');
}
return 0;
}
H
solver:lzh、zyh
题意是这样的:有n个人m个愿望,每个愿望都是一个二元组(x,y),代表第x个人不希望第y个人快乐。判断一个人是否快乐的条件是:这个人至少有一个愿望被满足。问:当至少\(m/4+1\)个愿望被满足时,哪些人是快乐的。
由于数据范围很大,所以我们不可能真的去找。做法是先rand每个人的情绪状态(是否快乐),然后根据这些情绪状态去遍历愿望,check有多少愿望被满足。不满足就继续rand。
这种做法的合理性在于m最大值仅仅为n的两倍,算不上稠密。否则check一次代价很大。
#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> pii;
#define ff first
#define ss second
#define mp make_pair
int a[200010], b[200010], tmp[200010], ans[200010];
//
int main()
{
srand(time(0));
int T;
scanf("%d", &T);
while (T--) {
int n, m;
scanf("%d%d", &n, &m);
int K = m / 4 + 1, cur = 0;
for (int i = 1, x, y; i <= m; i++)
scanf("%d%d", &a[i], &b[i]);
while (1) {
cur = 0;
for (int i = 1; i <= n; i++) {
tmp[i] = rand() & 1;
}
for (int i = 1; i <= m; i++)
ans[i] = 0;
for (int i = 1; i <= m; i++)
if (tmp[a[i]] && !tmp[b[i]])
cur++,ans[i]++;
if (cur >= K)
break;
}
printf("%d\n", cur);
for (int i = 1; i <= m; i++)
if (ans[i])
printf("%d ", i);
printf("\n");
}
}
I
solver:czq、zyh
略诡异的题目。由于其偏序性质,可以考虑构建有向图,拓扑排序后dp去做。
/* basic header */
#include <bits/stdc++.h>
/* define */
#define ll long long
#define pb emplace_back
#define mp make_pair
#define eps 1e-8
#define lson (curpos<<1)
#define rson (curpos<<1|1)
/* namespace */
using namespace std;
/* header end */
const int MAXN = 110;
int n, m, deg[MAXN], _rank[MAXN], vis[MAXN];
ll dp[MAXN];
int main() {
scanf("%d%d", &n, &m);
for (int u, v, i = 0; i < m; i++) {
scanf("%d%d", &u, &v);
u--, v--, deg[min(u, v)]++;
}
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
if (!vis[j])
if (deg[i]) deg[i]--;
else {
_rank[i] = j;
vis[j] = 1;
break;
}
_rank[n] = n;
for (int i = 0; i <= n; i++) {
for (int maxRank = -1, j = i - 1; j >= 0; j--)
if (_rank[j] > maxRank && _rank[i] > _rank[j])
maxRank = _rank[j], dp[i] += dp[j];
dp[i] = max(1LL, dp[i]);
}
printf("%lld\n", dp[n]);
return 0;
}