A.Buildings
有 N 个建筑物排成一行。左起第 𝑖i 栋建筑的高度为 Hi 。确定是否有比左侧第一个建筑物更高的建筑物。如果存在这样的建筑物,从左边找到最左边的建筑物的位置。
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int main()
{
int n;
cin >> n;
vector<int>h(n);
int mn = -1,ans=-1;
for (int i = 0;i < n;i++) {
cin >> h[i];
if (i == 0) {
mn = h[i];
}
else {
if (h[i] > mn&&ans==-1) {
ans = i;
}
}
}
if (ans != -1)
cout << ans + 1;
else
cout << -1;
return 0;
}
B.AtCoder Amusement Park
给定n个团队,依次进入容纳k的景区,如果当前剩余的位置仍够容纳新的a[i],继续进入,否则下一次再进入,确定次数。
思路:直接遍历,够就加上,不够就下一次
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int main()
{
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int n, k;
cin >> n >> k;
vector<int>a(n);
for (int i = 0;i < n;i++) {
cin >> a[i];
}
int ans = 0;
int i = 0;
while (i < n) {
int s = a[i];
int j = i+1;
while (j < n && s+a[j] <= k) {
s += a[j++];
}
ans++;
i = j;
}
cout << ans;
return 0;
}
C.Sigma Problem
给定x,y,f(x,y)=(x+y)%1e8,n个整数求∑(N−1,j)∑(N,i)f(Ai,Aj).
思路:先排序,在顺序遍历,当前数为a[i],在i+1~n中二分找到a[i]+a[j]>=1e8的个数m,最后减去m*1e8,加上sum*(n-1),每个数被加了n-1次。
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
typedef long long ll;
int main()
{
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int mod = 1e8;
ll n;
cin >> n;
vector<ll>a(n);
ll sum = 0;
for (int i = 0;i < n;i++) {
cin >> a[i];
}
sort(a.begin(), a.end());
ll num = 0;
for (int i = 0;i < n;i++) {
ll t = mod - a[i];
int j = lower_bound(a.begin()+i, a.end(), t)-a.begin();
if (j == i)++j;
num += n-j;
sum += a[i];
}
ll ans = sum * (n-1) - mod * num;
cout << ans;
return 0;
}
D.Another Sigma Problem
给定x,y,f(x,y)=xy(x,y串连起来),求∑(N−1,j)∑(N,i)f(Ai,Aj).
思路:前缀和,求出i~n的和,对于当前a[i]要乘多少,由i以后的数的位数决定,预处理i~n的数的位数之和,只需要a[i]*prod[i+1]即可求出a[i]与之后的数串联起来a[i]相应的值,再加上a[i]之后的数之和就可以了。
#include <iostream>
#include<vector>
#include<map>
#include<set>
#include<cmath>
#include<algorithm>
#include<queue>
#include<functional>
#include<numeric>
#include<unordered_map>
using namespace std;
typedef long long ll;
ll get_bit(ll x) {
ll s = 0;
while (x) {
x /= 10;
s++;
}
return s;
}
ll Pow(ll x) {
ll s = 1;
ll t = get_bit(x);
while (t) {
s *= 10;
t--;
}
return s;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int n;
cin >> n;
ll mod = 998244353;
vector<ll>a(n + 1), suf(n + 1, 0),prod(n+1,0);
for (int i = 1;i <= n;i++) {
cin >> a[i];
prod[i] = Pow(a[i]);
a[i] %= mod;
}
suf[n] = a[n];
for (int i = n - 1;i > 0;i--) {
suf[i] = (suf[i + 1] + a[i]) % mod;
prod[i] = (prod[i + 1] + prod[i]) % mod;
}
ll ans = 0;
for (int i = 1;i < n;i++) {
ans = (ans+a[i]*prod[i+1]) % mod;
ans = (ans + suf[i + 1]) % mod;
}
cout << ans;
return 0;
}
E.Yet Another Sigma Problem
给定字符串x,y,f(x,y)=x 和 𝑦 的最长公共前缀的长度,求∑(N−1,j)∑(N,i)f(Ai,Aj).
思路:用字典树来预处理,再遍历每个字符串,去掉当前字符串中字母在树中出现的次数,对于当前是否是最长公共前缀这个问题,我们每次求出当前前缀字符串和上一个前缀字符串出现的次数,差值即为最长公共前缀的个数,最后再处理最后一个位置即可。
#include<iostream>
#include<algorithm>
#include<unordered_map>
#include<vector>
using namespace std;
typedef long long ll;
const int N = 1e5 + 2;
struct Node {
unordered_map<char, Node*>mp;
ll cnt;
Node() { cnt = 0; }
};
Node* root = new Node();
void build_tree(string& s) {
Node* p = root;
for (auto& c : s) {
if (!p->mp.count(c)) {
p->mp[c] = new Node();
}
p->mp[c]->cnt++;
p = p->mp[c];
}
}
void remove_node(string& s) {
Node* p = root;
for (auto& c : s) {
p->mp[c]->cnt--;
p = p->mp[c];
}
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int n;
cin >> n;
vector<string>a(n);
for (int i = 0;i < n;i++) {
cin >> a[i];
build_tree(a[i]);
}
ll ans = 0;
for (int i = 0;i < n-1;i++) {
remove_node(a[i]);
Node* p = root;
if (a[i].size() == 1) {
ans += p->mp[a[i][0]]->cnt;
continue;
}
ll pre = p->mp[a[i][0]]->cnt, cur = 0;
p = p->mp[a[i][0]];
for (int j = 1;j < a[i].size();j++) {
cur = p->mp[a[i][j]]->cnt;
ans += (pre - cur)*j;
pre = cur;
p = p->mp[a[i][j]];
}
ans += pre * ll(a[i].size());
}
cout << ans;
return 0;
}