A. Satisfying Constraints

题意:给一个n,表示有n个操作,每个操作输入a,b,a假如是1,说明要大于等于b,a假如是2,要小于等于b,a假如是3,要求不等于b,然后求能满足所有操作的k值有多少个,因为要求满足操作,所以对于a=1.2来说,就是要求所有操作的交集,至于c,先求出交集数,再把满足1,2操作的c的数目全部减去就对了

代码:

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
void test()
{
ll n,t1=0,t2=INT_MAX,sum=0;
cin>>n;
vector<ll>v;
while(n--)
{
ll a,b;
cin>>a>>b;
if(a==1)
{
t1=max(t1,b);
}else if(a==2)
{
t2=min(t2,b);
}else{
v.push_back(b);
}
}
if(t1>t2||t1==INT_MAX||t2==0)
{
cout<<0<<endl;
return ;
}

sum=t2-t1+1;
map<ll,ll>mf;
for(int i=0;i<v.size();i++)
{
if(v[i]>=t1&&v[i]<=t2&&!mf[v[i]]) {
sum--;
mf[v[i]]++;
}
}
cout<<sum<<endl;
}
int main() {
int t;
cin >> t;

while (t--) {
test();
}

return 0;
}

B. Summation Game

题意:给一个数组,数组大小n,最多可以移除的次数k,最多可以乘于-1的次数x,k和x分别代表两个人的操作,k的希望数组和最后最大化,x的希望数组和最后最小化

数组内的值全部都大于等于1,然后求数组最大是多少

思路:首先我们排序,让它变的有序,然后我们可以一个一个的尝试,又因为我们都知道x的次数肯定会全用,所以用一个数组记录前缀和,那么数组距离差x的,用一个变量去记录最大的值是多少,先用sum表示所有数组和,然后再从数组后面开始尝试,因为-1肯定只会乘以最大的数,对不取当前数和原来的最大值比较,最后得出值就是最大值

代码:

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
void test()
{
ll n,k,x,sum=0,_max=INT_MIN;
cin>>n>>k>>x;
vector<ll>v(n+1);
vector<ll>vk(n+1);
for(int i=1;i<=n;i++)
cin>>v[i],sum+=v[i];
sort(v.begin()+1,v.end());
vk[0]=0,v[0]=0;
for(int i=1;i<=n;i++)
{
vk[i]=vk[i-1]+v[i];
}
for(int i=n;i>=n-k;i--)
{
if(i-x>=0)
_max=max(_max,sum-(vk[i]-vk[i-x])+(-1*(vk[i]-vk[i-x])));
else{
_max=max(_max,sum-(vk[i]-vk[i-i])+(-1*(vk[i]-vk[i-i])));
}
sum-=v[i];
// _max=max(sum,_max);
}
if(n<=k)
_max=max((ll)0,_max);
cout<<_max<<endl;
}
int main() {
int t;
cin >> t;

while (t--) {
test();
}

return 0;
}

C. Partitioning the Array

题意,给一个数组,求将数组划分成几个数组大小相等的子数组,然后寻找一个m,子数组的数对m求模后,得到的数放在原位,子数组如果都相等,那么分数加1,求最大分数

思路:首先对数组分割成子数组,肯定只能分割成数组大小的因子大小的子数组,然后是如何求满足题意的m,首先对m求模后,子数组要求都相等,那么我们可以认定,子数组与子数组之间,只能差为m的倍数或者是0,所以可以对划分出的数组值,跳跃式的求差,假如差之间的最大公约数不等于1,因为m>=2,所以m不存在1的情况

代码:

#include <iostream>
#include <vector>
#include <cmath>
using namespace std;

bool check(vector<int> &a, int k)
{
int n = a.size();
int g = 0;
for (int i = 0; i < n; i++)
{
if (i + k < n)
{
if (a[i] == a[i + k])
continue;
g = __gcd(g, abs(a[i + k] - a[i]));
}
}
if (g != 1)
return true;
else
return false;
}

void solve()
{
int n;
cin >> n;
vector<int> a(n);
for (int i = 0; i < n; i++)
cin >> a[i];
int ans = 0;
for (int i = 1; i <= n; i++)
{
if (n % i == 0)
{
if (check(a, i))
{
//cout << i << " ";
ans++;
}
}
}
cout << ans << "\n";
}

int main()
{
int t;
cin >> t;
//t=1;
while (t--)
{
solve();
}
return 0;
}

D. Array Repetition

题意:给一个n代表操作数,q代表查询数,n次操作,输入a,b,如果a=1,那么会对一个数组进行后面的插入,如果a=2,那么会将前面的数组copy,然后放到数组后面,存放次数是b,q次查询都是,输入c,然后查询数组c的位置的数,输出出去

思路:模拟,将vector存起来,然后这个vector储存起来,用b代表这次copy放了多少个,这样在遍历时候可以去取模计算

ps:这个题是看别人的思路和代码学懂的,另外也学到了__int128_t,否则出错

代码:

#include <iostream>
#include <cstring>
#include <vector>
using namespace std;
using LL = long long;

struct Node {
__int128_t total = 0;
vector<int> values;
};

int main() {

cin.tie(0);
cout.tie(0);
ios::sync_with_stdio(0);

const LL INF = 1e18;
int T;
cin >> T;
while (T--) {
int n, q;
cin >> n >> q;
vector<Node> nodes;
nodes.push_back({0, {}});
__int128_t curTotal = 0;
for (int i = 0; i < n; i++) {
int op, x;
cin >> op >> x;
if (curTotal > INF) continue;
if (op == 1) {
nodes.back().values.push_back(x);
curTotal += 1;
} else {
if (curTotal != 0) {
curTotal *= x + 1;
nodes.push_back({curTotal, {}});
}
}
}
while (q--) {
LL x;
cin >> x;
for (int i = nodes.size() - 1; i >= 0; i--) {
if (x > nodes[i].total) {
cout << nodes[i].values[x - nodes[i].total - 1] << ' ';
break;
}
x %= nodes[i - 1].total + nodes[i - 1].values.size();
if (x == 0) x += nodes[i - 1].total + nodes[i - 1].values.size();
}
}
cout << '\n';
}

return 0;
}

posted on 2024-01-14 07:41  塔罗-太阳  阅读(79)  评论(0)    收藏  举报