D. Digital string maximization
题目大意:给你一个0-9的字符串,你可以选择除首元素以外,并且大于0的元素,将其减一,并与其左边的元素交换,要求得到字典序最大的串
#1 理想情况下,每个元素最多可以被处理8次
#2 只有当当前元素比其左边的元素最少大2时,处理起来才是有价值的
思路:O(n)*10的情况下暴力枚举即可
代码:
void solve()
{
string s; cin >> s;
int n = s.size();
vector<int> v(n);
for (int i = 0; i < n; i ++ )
v[i] = s[i] - '0';
for (int i = 1; i < n ; i ++ )
{
int j = i;
while (v[j] > 0 && j > 0 && v[j] > v[j-1] + 1) v[j] -- ,swap(v[j-1], v[j]), j -- ;
}
for (int i = 0; i < n; i ++ )
cout << v[i];
cout << endl;
}
C. Kevin and Binary Strings
题目大意:给你一个以1开头的二进制01串,从中任意选取两条连续的且可包含前缀0的子串,使得到的异或和最大
#1 其中一条一定是原串
#2 从高位到低位找到第一个0的数位
#3 考虑全为1的情况
思路:全为1则随意输出一个位置,由于串中一定包含1,即可以将其放在第一个0位上,还有些情况需要判断,但此题数据范围小。可以直接枚举长度,进行匹配判断
代码:
void solve()
{
string s; cin >> s;
int pos = -1;
int n = s.size();
s = ' ' + s;
for (int i = 1; i <= s.size(); i ++ )
if (s[i] == '0')
{
pos = i;
break;
}
if (pos == -1)
{
cout<<1<<" "<<n<<" "<<1<<" "<<1<<endl;
}
else
{
cout<<1<<" "<<n<<" ";
int l = -1, r = -1, mx = 0,len = n - pos + 1;
string tmp = s.substr(pos,len);
for (int i = 1; i + len - 1 <= n; i ++ )
{
int sum = 0;
for (int j = 0; j < len; j ++ )
{
if ((tmp[j] ^ s[i+j]) == 1) sum ++ ;
else break;
}
if (mx <= sum) l = i, r = i + len - 1, mx = sum;
}
cout<<l<<" "<<r<<endl;
}
}
B. Outstanding Impressionist
题目大意:告诉你有一个n个元素的数组,具体值不知道,但知道范围,问你,对于每个元素wi,能否确定一个数组,使wi不等于其他w,数组不是唯一的
#1 除wi外,其他元素可以相等
思路:对于其他元素,只有当只能取一个值时,才能影响到wi的范围取定,当wi取不了值的时候,就不能构造出这样一个数组,首先预处理所有元素的贡献,当算到l==r的wi的时,要忽视自身的贡献,可以开个map记录;
代码:
void solve()
{
int n;
cin >> n;
vector<PII> segs(n);
vector<int> pre(2*n+2,1);
map<int,int> mp;
for (int i = 0; i < n; i ++ )
{
cin >> segs[i].x >> segs[i].y;
if (segs[i].x == segs[i].y)
pre[segs[i].y] = 0,mp[segs[i].y] ++;
}
for (int i = 1; i <= 2 * n; i ++ )
pre[i] += pre[i-1];
for (int i = 0; i < n; i ++ )
{
if (segs[i].x == segs[i].y)
{
if (mp[segs[i].x] == 1) cout<<1;
else cout<<0;
}
else
{
if (pre[segs[i].y] - pre[segs[i].x - 1]) cout<<1;
else cout<<0;
}
}
cout<<endl;
}
E. Insane Problem
题目大意:给你两个范围l1,r1,l2,r2和k,让你算有多少对{x,y},l1<= x <= r1, l2 <= y <= r2,使得y/x = k^n,n为非负整数
#1 特判k等于1
#2 公式可以变为x = y/(k^n)
#3 注意上界向下取整,下界向上取整
#注意判断交集的方法
代码:
void solve()
{
i64 k,l1,l2,r1,r2;
cin >> k >> l1 >> r1 >> l2 >> r2;
i64 x = 1, ans = 0;
if (k == 1)
{
ans = max(0LL,min(r2,r1) - max(l1,l2) + 1);
}
else
{
while (x <= r2)
{
i64 down = (l2 + x - 1) / x;
i64 up = r2 / x;
ans += max(0LL,min(r1 ,up )- max(l1,down) + 1);
x *= k;
}
}
cout<<ans<<endl;
}