2024ICPC区域赛成都站
- define时间:
#define itn int
#define int long long
#define ind long double
#define yes cout << "Yes"
#define no cout << "No"
#define pii pair<long long, long long>
#define pci pair<char, int>
#define re return;
L. Recover Statistics
签到。
其中 Px 的意义为:数列中恰好有 x% 的数小于等于这个值。
void solve()
{
cin >> x >> y >> z;
cout << 100 << '\n';
for (int i = 1; i <= 50; i++)
{
cout << x << ' ';
}
for (int i = 51; i <= 95; i++)
{
cout << y << ' ';
}
for (int i = 96; i <= 99; i++)
{
cout << z << ' ';
}
cout << z + 1;
}
J. Grand Prix of Ballance
模拟。
看懂题目即可,注意一次只会开放一个关卡,后续的其他指令也只有关于这个关卡才会被响应。
pii sum[N];
set<int> st[N], st1[N];
void solve()
{
cin >> n >> m >> k;
for (int i = 1; i <= n; i++)
{
fg[i] = 0;
st[i].clear(); //记录有排名的
st1[i].clear();//记录放弃的
}
for (int i = 1; i <= m; i++)
{
sum[i].second = 0; //分数
sum[i].first = i; //编号
}
int now;//记录当前关卡编号
while (k--)
{
int op;
cin >> op >> x;
if (op == 1)
{
now = x;
}
else if (op == 2)
{
cin >> y;
if (now == y)
{
if (st[y].find(x) == st[y].end() && st1[y].find(x) == st1[y].end())
{
sum[x].second += m - st[y].size();
st[y].insert(x);
}
}
}
else
{
cin >> y;
if (now == y)
{
if (st[y].find(x) == st[y].end() && st1[y].find(x) == st1[y].end())
{
st1[y].insert(x);
}
}
}
}
sort(sum + 1, sum + m + 1, [&](auto x, auto y)
{
if(x.second != y.second) return x.second > y.second;
return x.first < y.first; });
for (int i = 1; i <= m; i++)
{
cout << sum[i].first << ' ' << sum[i].second << '\n';
}
}
G. Expanding Array
位运算。
void solve() {
set<int>st;
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
for(int i=1;i<=n-1;i++){
x=a[i],y=a[i+1];
z=x|y;
st.insert(x);
st.insert(y);
st.insert(z);
st.insert(x&y);
st.insert(x^y);
st.insert(z^x);
st.insert(y^z);
st.insert(0);
}
cout<<st.size();
}
A. Arrow a Row
构造。
void solve()
{
cin >> s1;
num = 0;
vector<pii> v;
n = s1.size();
for (auto i : s1)
{
if (i == '-')
{
num++;
}
}
cnt = 0;
if (!num || n < 5)
{
cout << "No";
re;
}
if (s1[0] != '>' || s1.substr(s1.size() - 3, 3) != ">>>")
{
cout << "No";
re;
}
for (int i = n - 1; i >= 0; i--)
{
if (s1[i] == '>')
{
cnt++;
}
else
{
break;
}
}
cout << "Yes ";
for (int i = cnt; i > 3; i--)
{
v.emplace_back(n - 4, 5);
n--;
}
for (int i = 0; i < n - 3; i++)
{
if (s1[i] == '>')
{
v.emplace_back(i + 1, n - i);
}
}
cout << v.size() << '\n';
for (auto j : v)
{
cout << j.first << ' ' << j.second << '\n';
}
}
I. Good Partitions
思维。
题意:给定一个数字序列和 \(k\) 次修改,每次修改 \(a[x]=y\),有 \(k+1\) 次询问:
将序列分割为以 \(m\) 为间隔的小段,每小段满足非递减。问 \(m\) 可能的值有多少个。
思路:我们可以考虑如果 \(a[i-1]>a[i]\),说明这个点将作为分割点,放入set。
又发现最后所有分割点应该具有相同的间隔,我们只可能将大段切成小段。
于是我们可以转化题意:
对于第一个出现的分割点,遍历他的因子;只有后续所有分割点都是因子的倍数,才是可能的 \(m\)。
vector<int> e[N+5];
void solve()
{
set<int> st;
cin >> n >> k;
fill(b,b+N,0);
for (int i = 1; i <= n; i++)
{
cin >> a[i];
}
auto ck = [&]()
{
if (st.empty())
{
return n;
}
ans = 0;
auto minn = *st.begin();
for (auto i : e[minn])//遍历第一个分割点的因子
{
if (b[1] == b[i])//所有分割点都是该因子的倍数等价于此式
{
ans++;
}
}
return ans;
};
auto add = [&](int x)
{
st.insert(x);
for (auto j : e[x])
{
b[j]++;
}
};
auto sub = [&](int x)
{
st.erase(x);
for (auto j : e[x])
{
b[j]--;
}
};
for (int i = 2; i <= n; i++)
{
if (a[i - 1] > a[i])
{
add(i - 1);
}
}
cout << ck() << '\n';
while (k--)
{
cin >> x >> y;
if (x > 1 && a[x - 1] > a[x])
{
sub(x - 1);
}
if (x < n && a[x] > a[x + 1])
{
sub(x);
}
a[x] = y;
if (x > 1 && a[x - 1] > a[x])
{
add(x - 1);
}
if (x < n && a[x] > a[x + 1])
{
add(x);
}
cout << ck() << '\n';
}
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);
/* solve(); */
int T;
T = 1;
cin >> T;
for (int i = 1; i <= N; i++)//预处理因子
{
for (int j = i; j <= N; j += i)
{
e[j].emplace_back(i);
}
}
while (T--)
{
solve();
}
return 0;
}

浙公网安备 33010602011771号