牛客周赛 Round 95(A~F)
赛时没有Ak,今天做matlab作业做麻了
A.小红的数组查询(一)
思路:其实只和长度有关系,l==r,答案就为1,否则就为2
#include<bits/stdc++.h>
#define ll long long
#define endl '\n'
using namespace std;
const ll N=5e5+45;
const ll mod=998244353;
ll ksm(ll x,ll y) {
ll ans=1;
while (y) {
if (y&1)ans=ans*x%mod;
x=x*x%mod;
y>>=1;
}
return ans%mod;
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
ll l,r;
// vector<ll>a(200,0);
// a[1]=1;
// for (ll i=3;i<=105;i++)a[i]=a[i-2];
cin>>l>>r;
if (l==r)cout<<1<<endl;
else cout<<2<<endl;
}
B.小红的数组构造
思路:根据区间关系补差即可,除了第一个位置,\(b_i=a_i-a_{i-1}\)
#include<bits/stdc++.h>
#define ll long long
#define endl '\n'
using namespace std;
const ll N=5e5+45;
const ll mod=998244353;
ll ksm(ll x,ll y) {
ll ans=1;
while (y) {
if (y&1)ans=ans*x%mod;
x=x*x%mod;
y>>=1;
}
return ans%mod;
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
ll n;
cin>>n;
vector<ll>a(n+5);
for (ll i=1;i<=n;i++)cin>>a[i];
ll q;
cin>>q;
while (q--) {
ll l,r;
cin>>l>>r;
for (ll i=l;i<=r;i++) {
if (i==l)cout<<a[i]<<" ";
else cout<<a[i]-a[i-1]<<" ";
}
cout<<endl;
}
}
C.小红的数组查询(二)
思路:我们发现其周期性出现,就是d加了很多次变成p的倍数了,那么周期长就是d和p的最小倍数/d,然后和区间长取个min即可
吐槽:赛时没看出p=1时特殊情况,直接走了(一直wa1个点没过,脑袋涨涨的,不想想了)
#include<bits/stdc++.h>
#define ll long long
#define endl '\n'
using namespace std;
const ll N=5e5+45;
const ll mod=998244353;
ll ksm(ll x,ll y) {
ll ans=1;
while (y) {
if (y&1)ans=ans*x%mod;
x=x*x%mod;
y>>=1;
}
return ans%mod;
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
ll d,p;
cin>>d>>p;
ll q;
cin>>q;
while (q--) {
ll l,r;
cin>>l>>r;
if (p==1) {
if (l==r)cout<<1<<endl;
else if(l>=2)cout<<1<<endl;
else cout<<2<<endl;
continue;
}
// if (p%d==0) {
// cout<<min(p/d,r-l+1)<<endl;
// }
// else {
cout<<min(p/__gcd(p,d),r-l+1)<<endl;
// }
}
}
D.小红的区间修改(一)
思路:如果在知道这个区间有没有数字>0,那么我们可以很快的解决这道问题。我们考虑用set修改区间下标即可,每次去修改区间有没有修改过,如果有,则跳过,否则暴力遍历,并修改答案
#include<bits/stdc++.h>
#define ll long long
#define endl '\n'
using namespace std;
const ll N=5e5+45;
const ll mod=998244353;
ll ksm(ll x,ll y) {
ll ans=1;
while (y) {
if (y&1)ans=ans*x%mod;
x=x*x%mod;
y>>=1;
}
return ans%mod;
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
ll q;
cin>>q;
vector<ll>a(350000,0);
set<ll>k;
ll ans=1;
ll z=0;
for (ll i=1;i<=q;i++) {
ll l,r;
cin>>l>>r;
if (k.size()==0) {
for (ll j=l;j<=r;j++) {
k.insert(j);
}
ans+=r-l+1;
z=r-l+1;
}
else {
auto j=k.lower_bound(l);
if (j==k.end()||(*j)>r) {
for (ll j=l;j<=r;j++)k.insert(j);
if (z<=r-l+1) {
ans+=r-l+1-z;
z=r-l+1;
}
}
}
cout<<ans<<endl;
}
}
E.小红的数组操作
思路:答案无非就是只对左边,只对右边,和对左右进行覆盖或者不覆盖这四种情况取最优,那么这里给出一个通用方法,以一个循环作为左端点,然后单指针维护右端点,知道跳到加入个这个点时,数字出现次数大于等于2就不加了。此时只需单调维护cost(从现在往右覆盖)的最小值,也需要对于此时加入点右边的一个点取个min,然后对i所在位置取个左边覆盖值和i-1取个左边覆盖值最小,然后两者的加和取所有可能min即可得出答案
#include<bits/stdc++.h>
#define ll long long
#define endl '\n'
using namespace std;
const ll N=5e5+45;
const ll mod=998244353;
ll ksm(ll x,ll y) {
ll ans=1;
while (y) {
if (y&1)ans=ans*x%mod;
x=x*x%mod;
y>>=1;
}
return ans%mod;
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
ll n;
cin>>n;
vector<ll>a(n+5,0);
map<ll,ll>f2;
ll ans=1e18;
for (ll i=1;i<=n;i++)cin>>a[i];
ll r=1;
ll cost=1e18;
for (ll i=1;i<=n;i++) {
while (r!=n+1&&f2[a[r]]==0) {
f2[a[r]]++;
cost=min(cost,a[r]*(n-r+1));
r++;
}
cost=min(cost,a[r]*(n-r+1));
ans=min(ans,min(a[i]*i+cost,a[i-1]*(i-1)+cost));
f2[a[i]]--;
}
cout<<ans<<endl;
}
F.小红的区间修改(二)
思路:打过今年郑州或者补过郑州C的人,应该一眼可以发现两个的覆盖模式很像,而且这个覆盖更简单(无需区间合并),所以直接暴力维护修改区间,并清除被覆盖区间和添加新区间,由于偷懒。毕竟牛客周赛不卡map,于是全用map+set写了。
赛时没看出来哪里错了,赛后一看=写出==了,改了就过了,QwQ
#include<bits/stdc++.h>
#define ll long long
#define endl '\n'
using namespace std;
const ll N=5e5+45;
const ll mod=998244353;
ll ksm(ll x,ll y) {
ll ans=1;
while (y) {
if (y&1)ans=ans*x%mod;
x=x*x%mod;
y>>=1;
}
return ans%mod;
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
ll q;
cin>>q;
set<pair<ll,ll>>k;
map<pair<ll,ll>,ll>f1;
map<ll,ll>f2;
ll ans=1;
k.insert({1,100005});
f2[0]=5000000;
f1[{1,100005}]=0;
while (q--) {
ll l,r,d;
cin>>l>>r>>d;
ll c=l,e=r;
vector<pair<ll,ll>>add,del;
add.push_back({l,r});
f2[d]++;
if (f2[d]==1)ans++;
while (1) {
auto j=k.upper_bound({l,1e18});//第一个小于等于l的区间
j--;
auto [x,y]=(*j);
del.push_back({x,y});
f2[f1[{x,y}]]--;
ll xx=f1[{x,y}];
if (f2[xx]==0)ans--;
if (x!=l)
{
add.push_back({x,l-1});
f1[{x,l-1}]=xx;
f2[xx]++;
if (f2[xx]==1)ans++;
}
if (r<y) {
add.push_back({r+1,y});
f1[{r+1,y}]=xx;
f2[xx]++;
if (f2[xx]==1)ans++;
}
l=y+1;
if (l>r)break;
}
for (auto [x,y]:del)k.erase({x,y});
for (auto [x,y]:add)k.insert({x,y});
del.clear(),add.clear();
f1[{c,e}]=d;
cout<<ans<<endl;
}
}

浙公网安备 33010602011771号