练一套div3
A - Round Down the Price
#include<iostream>
#include<bits/stdc++.h>
using namespace std;
#define four(i, a, b) for(int i=a;i<=b;i++)
#define fourr(i, a, b) for(int i=a;i>=b;i--)
#define Max(a, b) (a>b?a:b)
#define Min(a, b) (a<b?a:b)
#define ll long long
#define inf 0x3f3f3f3f
#define mem(a, b) memset(a,b,sizeof(a))
#define lowbit(x) (x&(-x))
const ll maxn = 1e3 + 5;
const ll maxm = 1e5 + 5;
const ll mod = 233333;
int t;
int fun(int m){
int b=1;
while(m>b){
b*=10;
}
if (m<b)b/=10;
return b;
}
void sol(){
int m;
scanf("%d",&m);
cout<<m- fun(m)<<endl;
}
int main() {
scanf("%d",&t);
while(t--){
sol();
}
}
B - Polycarp Writes a String from Memory
#include<iostream>
#include<bits/stdc++.h>
using namespace std;
#define four(i, a, b) for(int i=a;i<=b;i++)
#define fourr(i, a, b) for(int i=a;i>=b;i--)
#define Max(a, b) (a>b?a:b)
#define Min(a, b) (a<b?a:b)
#define ll long long
#define inf 0x3f3f3f3f
#define mem(a, b) memset(a,b,sizeof(a))
#define lowbit(x) (x&(-x))
const ll maxn = 2e5 + 5;
const ll maxm = 1e5 + 5;
const ll mod = 233333;
int t;
char s[maxn];
bool vis[30];
void sol() {
mem(vis,0);
scanf("%s", s);
int len = strlen(s);
int ans = 1;
int lim=0;
for (int i = 0; s[i];) {
while (vis[s[i]-'a'])
i++;
if (!s[i])break;
if (lim >= 3) {
ans++;
lim = 0;
mem(vis,0);
}else{
lim++;
vis[s[i++]-'a']=1;
}
}
cout<<ans<<endl;
}
int main() {
scanf("%d", &t);
while (t--) {
sol();
}
}
C - Train and Queries
两个map记录一下每个数字出现的最早位置和最晚位置,然后比较即可
#include<iostream>
#include<bits/stdc++.h>
using namespace std;
#define four(i, a, b) for(int i=a;i<=b;i++)
#define fourr(i, a, b) for(int i=a;i>=b;i--)
#define Max(a, b) (a>b?a:b)
#define Min(a, b) (a<b?a:b)
#define ll long long
#define inf 0x3f3f3f3f
#define mem(a, b) memset(a,b,sizeof(a))
#define lowbit(x) (x&(-x))
const ll maxn = 2e5 + 5;
const ll maxm = 1e5 + 5;
const ll mod = 233333;
int t;
int a[maxn];
map<int, int> pos[2];
void sol() {
int n, m;
scanf("%d%d", &n, &m);
pos[1].clear();
pos[0].clear();
four(i, 1, n) {
scanf("%d", &a[i]);
if (!pos[0][a[i]]) {
pos[1][a[i]] = pos[0][a[i]] = i;
} else {
pos[1][a[i]] = Max(pos[1][a[i]], i);
}
}
four(i, 1, m) {
int a, b;
scanf("%d%d", &a, &b);
if (!pos[0][a] || !pos[1][b])
puts("NO");
else if (pos[0][a] < pos[1][b])
puts("YES");
else
puts("NO");
}
}
int main() {
scanf("%d", &t);
while (t--) {
sol();
}
}
D - Not a Cheap String
开个结构体,存放下标、数据、是否删除的状态。
先根据数据排序,删最大的,这样步数一定最小,删的时候标记位改一下。
然后根据:先标记位后下标的优先级再排序就ok了
#include<iostream>
#include<bits/stdc++.h>
using namespace std;
#define four(i, a, b) for(int i=a;i<=b;i++)
#define fourr(i, a, b) for(int i=a;i>=b;i--)
#define Max(a, b) (a>b?a:b)
#define Min(a, b) (a<b?a:b)
#define ll long long
#define inf 0x3f3f3f3f
#define mem(a, b) memset(a,b,sizeof(a))
#define lowbit(x) (x&(-x))
const ll maxn = 2e5 + 5;
const ll maxm = 1e5 + 5;
const ll mod = 233333;
int t;
char s[maxn];
struct node{
char dt;
int id;
bool sta;
}st[maxn];
bool cmp(node a, node b){
return a.dt>b.dt;
}
bool cmp1(node a,node b){
if(a.sta==b.sta)return a.id<b.id;
return a.sta<b.sta;
}
void sol() {
scanf("%s",s);
int m;
scanf("%d",&m);
int len= strlen(s);
int sum=0;
for(int i=0;s[i];i++){
st[i].dt=s[i];
sum+=s[i]-'a'+1;
st[i].id=i;
st[i].sta=0;
}
sort(st,st+len,cmp);
int i=0;
while(sum>m&&i<len){
sum-=st[i].dt-'a'+1;
st[i].sta=1;
i++;
}
sort(st,st+len,cmp1);
for(i=0;!st[i].sta&&i<len;i++){
putchar(st[i].dt);
}
puts("");
}
int main() {
scanf("%d", &t);
while (t--) {
sol();
}
}
E - Split Into Two Sets
这题不会,好像是二分图,留坑
F - Equate Multisets
首先搞明白一个关键:b/2是为了分解非2质因子。
而b*2可以转换为a/2(a是偶数的情况)。
此时a/2的目的是去掉所有的因子2。
这样一来使a==b,就变成提取关键非2质因子了。
我们先把a、b全除成奇数,再一步一步拆b看看能不能拆出关键因子。
比如a30 b21,可以转换为a5 b21->10->5就得到关键因子5了。
关键质因子就是从其他非2质因子里拆出来的,所以一步步试就行了。
越大的关键质因子越要先凑,所以ab大顶堆。当b最大的元素比关键因子小了,说明凑不出来了,直接no。
#include<iostream>
#include<bits/stdc++.h>
using namespace std;
#define four(i, a, b) for(int i=a;i<=b;i++)
#define fourr(i, a, b) for(int i=a;i>=b;i--)
#define Max(a, b) (a>b?a:b)
#define Min(a, b) (a<b?a:b)
#define ll long long
#define inf 0x3f3f3f3f
#define mem(a, b) memset(a,b,sizeof(a))
#define lowbit(x) (x&(-x))
const ll maxn = 2e5 + 5;
const ll maxm = 1e5 + 5;
const ll mod = 233333;
int t;
int n;
//int a[maxn];
//int b[maxn];
void sol() {
scanf("%d", &n);
priority_queue<int> a, b;
int k;
four(i, 1, n) {
scanf("%d", &k);
while (k % 2 == 0) {
k /= 2;
}
a.push(k);
}
four(i, 1, n) {
scanf("%d", &k);
while (k % 2 == 0) {
k /= 2;
}
b.push(k);
}
while (!b.empty()) {
k = b.top();
b.pop();
if (k == a.top()) {
a.pop();
} else if (k < a.top()) {
puts("NO");
return;
} else {
k /= 2;
if (k % 2 == 0)k /= 2;
b.push(k);
}
}
puts("YES");
}
int main() {
cin >> t;
while (t--)
sol();
}
G2 Passable Paths (hard version)
挺难想的一道题(对我来说)看了别人的题解才有启发
确认序列都在一条链上就ok,换句话说就是走过的每个点分支不超过2。那么给这条链找端点p1,p2。
令p1是深度最大的点好理解。
令p2为p1异分支上的点,这样一旦有个点不在p1或p2的分支上就no了,同样让p2深度尽可能大,lca(p1,p2)!=p2就是异分支,如果找不到这个点,说明每个点都与p1同支,直接yes。
处理完p1p2之后,对每个p分别求lca(p1,p)=a1,lca(p2,p)=a2,lca(p1,p2)=a;在p合法的情况下,有:
- 若p与p1同支,那么a1应等于p,a2应等于a
- 若p与p2同支,那么a1应等于a,a2应等于p
符合其中一个就ok,不符合false
#include<iostream>
#include<bits/stdc++.h>
using namespace std;
//#pragma GCC optimize(3)
#define endl "\n"
#define four(i, a, b) for(int i=a;i<=b;i++)
#define fourr(i, a, b) for(int i=a;i>=b;i--)
#define Max(a, b) (a>b?a:b)
#define Min(a, b) (a<b?a:b)
#define ll long long
#define inf 0x3f3f3f3f
#define mem(a, b) memset(a,b,sizeof(a))
#define lowbit(x) (x&(-x))
const ll maxn = 2e5 + 5;
const ll maxm = 1e5 + 5;
const ll mod = 233333;
int d[maxn];
int f[maxn][20];
int n;
vector<int> v[maxn];
int queries[maxn];
int lca(int a, int b) {
if (d[a] != d[b]) {
if (d[a] < d[b])
swap(a, b);
int dis = d[a] - d[b];
for (int i = 0; (1 << i) <= n; ++i) {
if ((1 << i) & dis) {
a = f[a][i];
}
}
}
if (a == b)return a;
for (int i = 19; i >= 0; i--) {
if (f[a][i] != 0 && f[b][i] != 0 && f[a][i] != f[b][i]) {
a = f[a][i];
b = f[b][i];
}
}
return f[a][0];
}
void bfs() {
d[1] = 1;
queue<int> q;
q.push(1);
while (!q.empty()) {
int t = q.front();
q.pop();
for (const auto &item: v[t]) {
if (d[item]) continue;
d[item] = d[t] + 1;
f[item][0] = t;
for (int i = 1; i < 20; ++i) {
f[item][i] = f[f[item][i - 1]][i - 1];
}
q.push(item);
}
}
}
int main() {
// ios::sync_with_stdio(false);
// cin.tie(0);
// cout.tie(0);
cin >> n;
four(i, 1, n - 1) {
int a, b;
cin >> a >> b;
v[a].push_back(b);
v[b].push_back(a);
}
bfs();
int q;
cin >> q;
while (q--) {
int k;
cin >> k;
bool ok = 1;
int p1 = -1, p2 = -1;
four(i, 1, k) {
cin >> queries[i];
if (p1 == -1 || d[p1] < d[queries[i]])p1 = queries[i];
}
four(i, 1, k) {
if (queries[i] == p1)continue;
int t_lca = lca(p1, queries[i]);
if (t_lca != queries[i]) {
if (p2 == -1 || d[p2] < d[queries[i]])
p2 = queries[i];
}
}
if (p2 == -1)cout << "YES\n";
else {
four(i, 1, k) {
if (queries[i] == p1 || queries[i] == p2)
continue;
int a1 = lca(p1, queries[i]);
int a2 = lca(p2, queries[i]);
int a = lca(p1, p2);
if(!((a1==a&&a2==queries[i])||(a2==a&&a1==queries[i]))){
ok=0;
break;
}
}
puts((ok?"YES":"NO"));
}
}
}
总结:不会的东西太多,慢慢补。需要提高一下做题速度,简单的模拟上少花点时间。