Edu161 D、E 模拟+位运算构造
D. Berserk Monsters
codeforces.com/contest/1922/problem/D
模拟。
题意:给定n个怪物,a[i]为攻击,b[i]为护盾,每只怪物会受到相邻怪物的攻击,如果总攻击>护盾则死亡,输出n轮攻击各有多少只怪物死亡。
思路:首先容易发现一只怪物如果没死,那么他对其他怪物的攻击贡献无影响;
反之,假定ABCDE五只怪物,C死了,那么B受到C的攻击消失,加上受到D的攻击;D同理,加上受到B的攻击。
按照这个思路模拟。
void solve()
{cin >> n;set<int> st1, st2;a[0] = a[n + 1] = 0; //多测记得清零,会影响答案。rep(1, i, n){cin >> a[i];st1.insert(i);}rep(1, i, n){cin >> b[i];}rep(1, i, n){c[i] = a[i - 1] + a[i + 1];}rep(1, i, n){if (c[i] > b[i]){st2.insert(i);}}rep(1, j, n){vector<int> v;ans = st2.size();for (auto i : st2){auto tp = st1.find(i);auto l = tp;auto r = tp;if (r != --st1.end()){ // 找当前死亡的后一个位置r++;}if (l != st1.begin()){ // 找当前死亡的前一个位置l--;}auto r1 = *r; // 后一个位置的坐标auto l1 = *l; // 前一个坐标if (i != l1){c[l1] -= a[i];if (i != r1){c[l1] += a[r1];}}if (i != r1){c[r1] -= a[i];if (i != l1){c[r1] += a[l1];}}if (!st2.count(l1)){v.push_back(l1);}if (!st2.count(r1)){v.push_back(r1);}st1.erase(st1.find(i));}st2.clear();for (auto u : v){if (c[u] > b[u]){st2.insert(u);}}cout << ans << ' ';}
}
E. Increasing Subsequences
Problem - E - Codeforces
位运算+构造。
题意:给定一个<1e18的整数n,构造一个含有n个递增子序列的数组,并保证数组大小<=200。
思路:
我们可以举例找找规律,对于4可以构造[1 2],5可以在数列前加一个大数x [x 1 2],6可以在2前加 [1 x 2]。
我们发现这样插入一个大数不会影响原来的数量,如果设d为x插入后左侧数的数量,相当于+2d+2^d+2d。
据此我们可以找到构造方法:先找到t=log2(n),构造1-t。
然后联系n的二进制,从低到高位,如果当前位为1,则放入一个大数。
注意:log2函数不适合处理大数据,可以用位运算求log2,或在后加特判
void solve()
{cin >> n;x = 500;t = log2(n);/* cout << t << "\n"; */vector<int> v;if ((int)pow(2, t) > n)//特判一下,防止溢出{t--;}for (int i = 0; i < t; i++){if (i != 0){v.emplace_back(i);}if (n & (1ll << i)){v.emplace_back(x--);}}v.emplace_back(t);cout << v.size() << '\n';for (auto i : v){cout << i << ' ';}
}