上午看着学了下splay树,感觉比树套树好理解多了qaq,树套树可能就放一会儿了,现在对我来说难度有点大了,先把主席树玩儿好吧。
期末真的不能停训啊,现在思维上大退步,1000的题一遍过不掉,1500的题吗的天天卡,怀念期末前的状态了www
明天有集训队的训练赛,打打看,题目貌似不简单的样子…
题目链接
很一根筋的思维题,没有小脑都能做
#include
using namespace std;
#define int long long
using i64 = long long;
using i128 = __int128_t;
typedef pair<int, int> PII;
void solve()
{
int n;
cin >> n;
vector<int> a(n);
int cnt1 = 0, cnt2 = 0;
for (int i = 0; i < n; i ++ )
{
int x; cin >> x;
if (x > 0) cnt1 ++;
else cnt2 ++ ;
}
for (int i = 0; i < cnt1; i ++ ) cout << i + 1 << ' ';
for (int i = 0; i < cnt2; i ++ ) cout << cnt1 - i - 1 << ' ';
cout << '\n';
for (int i = 0; i < cnt2; i ++ ) cout << 1 << ' ' << 0 << ' ';
cnt1 -= cnt2;
for (int i = 0; i < cnt1; i ++ ) cout << i + 1 << ' ';
cout << '\n';
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t = 1;
cin >> t;
while (t -- )
{
solve();
}
}
题目链接
思路还没成型的时候千万不要上手敲代码啊啊啊,否则就会漏掉很重要的点
这题的本质是想到每轮查性别后用的笼子数量是猪的当前总数除以二加1就可以了
#include
using namespace std;
#define int long long
using i64 = long long;
using i128 = __int128_t;
typedef pair<int, int> PII;
void solve()
{
int n;
cin >> n;
vector<int> a(n);
for (int i = 0; i < n; i ++ ) cin >> a[i];
int maxx = 0, cnt = 0;
int sum = 0;
int used = 0;
for (int i = 0; i < n; i ++ )
{
if (a[i] == 1)
{
cnt ++ ;
sum ++ ;
}
else
{
if (cnt != 0)
{
used = max(maxx + cnt, used);
maxx = 1 + sum / 2;
used = max(used, maxx);
cnt = 0;
}
}
}
used = max(used, maxx + cnt);
cout << used << '\n';
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t = 1;
cin >> t;
while (t -- )
{
solve();
}
}
题目链接
这题的槽点就是题目说的是异或,我给看成or做了老半天
异或的话,不难想到要把所有2x2的小矩阵都统一成一个数,哪一个数呢,还是不难想到是0
我们观察到每一行相邻的两个元素都会被分到一个小矩阵里,每一列相邻的两个元素也都会被分到同一个小矩阵里,那就是要保证每一行的某几位数字要抵消(也就是相同),每一列的某几位数字也要抵消(相同),再加上这整个是一个二维矩阵,那么每一位就可以表示成a[i][j] = pow(2, 8) * i + j
(2的八次方是因为超过200)
(这可能也算一种技巧?不管了记下来吧)
#include
using namespace std;
#define int long long
using i64 = long long;
using i128 = __int128_t;
typedef pair<int, int> PII;
void solve()
{
int n, m;
cin >> n >> m;
int tmp = pow(2, 8);
cout << n * m << '\n';
for (int i = 0; i < n; i ++ )
{
for (int j = 0; j < m; j ++ )
cout << tmp * i + j << ' ';
cout << '\n';
}
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t = 1;
cin >> t;
while (t -- )
{
solve();
}
}
题目链接
把ab存进一个pair的数组里,对a从小到大排序,然后枚举当取到最大的a是a[i],此时的最小差值是多少
需要预处理出max_suf[i],存储在第i个之后b的最大值是多少
同时维护一个multiset,存放所有的b,枚举到a[i]的时候就把b[i]从中删去
我们取a[i]作为a的最大值,那么i之后的只能取b了,在其中如果b的最大值大于a[i],那答案就是两者之差,如果小于a[i],那就还需要在multiset里找距离a[i]最近的b再进一步判断
代码细节还蛮多的
#include
using namespace std;
#define int long long
#define inf 0x3f3f3f3f
using i64 = long long;
using i128 = __int128_t;
typedef pair<int, int> PII;
void solve()
{
int n;
cin >> n;
vector<PII> a(n);
multiset<int> max_pre;
for (int i = 0; i < n; i ++ )
{
cin >> a[i].first >> a[i].second;
max_pre.insert(a[i].second);
}
sort(a.begin(), a.end());
vector<int> max_suf(n);
int maxtmp = 0;
for (int i = n - 1; i >= 0; i -- )
{
max_suf[i] = maxtmp;
maxtmp = max(maxtmp, a[i].second);
}
int ans = inf;
for (int i = 0; i < n; i ++ )
{
max_pre.erase(max_pre.lower_bound(a[i].second));
if (i != n - 1 && max_suf[i] >= a[i].first) ans = min(ans, abs(max_suf[i] - a[i].first));
else
{
auto pos = max_pre.lower_bound(a[i].first);
if (pos != max_pre.end())ans = min(ans, abs(*pos - a[i].first));
if (pos != max_pre.begin()) pos = prev(pos);
ans = min(ans, abs(a[i].first - *pos));
}
if (ans == 0) break;
max_pre.insert(a[i].second);
}
cout << ans << '\n';
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t = 1;
cin >> t;
while (t -- )
{
solve();
}
}