题意:给定一个数组a,你寻求一个数组b,使得相邻两项可以被整除,且 $2 \sum \limits_{i = 1}^{n} |a_i - b_i| \le S$
思路:可以发现,当我们把所有奇数项或偶数项都赋值为1,那么就可以满足整除,是奇数为1还是偶数为1,取决于奇数项的和大还是偶数项的和大,将大的为1,小的与a对应即可
diamond:
#include<bits/stdc++.h>
using namespace std;
#define int long long
void solve(){
int s1=0;
int s2=0;
int n;
cin>>n;
vector<int>g(n);
for (int i = 0; i <n ; ++i) {
cin>>g[i];
if(i&1)s1+=g[i];
else s2+=g[i];
}
if(s1<s2){
for (int i = 0; i <n ; ++i) {
if(i&1)cout<<'1'<<' ';
else cout<<g[i]<<' ';
}
}
else {
for (int i = 0; i <n ; ++i) {
if((i&1)==0)cout<<'1'<<' ';
else cout<<g[i]<<' ';
}
}
cout<<endl;
}
int32_t main() {
int t;
cin>>t;
while (t--){
solve();
}
return 0;
}
题意:一个机器人在数轴上,0秒在0,会给它n个指令,一个指令含有两个值,ti和xi,表示他要在ti秒时往xi这个点走,假设他在1秒前往5,在2s接到一个指令前往1,那么这个指令会被忽略,因为1秒的指令还未结束,如果一个指令是成功的,那么就是在ti到t(i+1)的时间里,经过了xi,问成功指令有多少
思路:模拟,我们记录当前执行的指令的起点qd,和终点zd,以及指令结束的时间nexttime,lsttime记录的是执行的哪个指令,然后我们更新即可
-
当我们当前指令的t在上一个执行的指令结束时间nexttime之后,我们执行当前指令,更新这些参数,如果nexttime<=a[i+1].t,那么就是成功的指令。
-
else,我们计算当前走到了哪儿,以及a[i+1].t走到了哪儿,x在两者之间,就是成功指令
diamond:
#include<bits/stdc++.h>
using namespace std;
#define int long long
struct node{
int t,x;
};
void solve(){
int n;
cin>>n;
vector<node>a(n+1);
for (int i = 0; i <n ; ++i) {
cin>>a[i].t>>a[i].x;
}
a[n].t=1e15;
int ans=0;
int qd=0,zd=0,nexttime=0,lstime=0;
for(int i = 0; i <n ; ++i) {
if(a[i].t>= nexttime){
nexttime=a[i].t+abs(a[i].x-zd);
qd=zd,zd=a[i].x;
lstime=i;
if(nexttime<=a[i+1].t){
ans++;
}
}
else{
if(qd>=zd){
int y=qd-(a[i].t-a[lstime].t);
int x=max(zd,qd-(a[i+1].t-a[lstime].t));
if(a[i].x>=x&&a[i].x<=y){
ans++;
}
}
else{
int x=qd+a[i].t-a[lstime].t;
int y=min(zd,qd+a[i+1].t-a[lstime].t);
if(a[i].x>=x&&a[i].x<=y){
ans++;
}
}
}
}
cout<<ans<<endl;
}
int32_t main() {
int t;
cin>>t;
while (t--){
solve();
}
return 0;
}
题意:初始值为0,给定一个字符串,操作分为+和-,+就是加一,-是减一,给q个询问,每个询问包含l和r,将l到r的操作忽略之后,执行字符串中的操作共可以得到几个值
思路:假如- + - - + - - +,将1到8 忽略,只能得到0这一个值,由于操作是+1或-1,因此我们只需得到这个操作过程中的最大值和最小值,差+1就是答案,我们可以发现,当我们将中间的操作忽略之后,其实就是保留l-1之前的操作以及和r+1之后的操作,画图易知,进行一个前缀和,将r+1之后的数字加到l-1那个地方,对0到l取min和max,和操作后的r到n进行取min和max,求出答案,我们要考虑到没有右边的情况,以及max>=0,mi<=0;
diamond:
#include<bits/stdc++.h>
using namespace std;
#define int long long
int b[200010],c[200010],lmax[200010],lmin[200010],rmax[200010],rmin[200010];
int32_t main() {
int t;
cin>>t;
while(t--){
int n,k;
cin>>n>>k;
b[0]=0;
for(int i=1;i<=n+5;i++){
b[i]=0;
c[i]=0;
lmax[i]=LLONG_MIN;
lmin[i]=LLONG_MAX;
rmax[i]=LLONG_MIN;
rmin[i]=LLONG_MAX;
}
lmax[0]=0;
lmin[0]=0;
rmin[n+1]=0;
rmax[n+1]=0;
string s;
cin>>s;
s="0"+s;
for(int i=1;i<=n;i++){
if(s[i]=='-'){
b[i]=b[i-1]-1;
}
else{
b[i]=b[i-1]+1;
}
// cout<<i<<" "<<b[i]<<endl;
}
lmax[1]=b[1];
lmin[1]=b[1];
for(int i=2;i<=n;i++){
//c[i]=c[i-1]+b[i];
lmax[i]=max(lmax[i-1],b[i]);
lmin[i]=min(lmin[i-1],b[i]);
}
rmax[n]=b[n];
rmin[n]=b[n];
for(int i=n-1;i>0;i--){
rmax[i]=max(rmax[i+1],b[i]);
rmin[i]=min(rmin[i+1],b[i]);
}
for(int i=1;i<=k;i++){
int l,r;
cin>>l>>r;
int d=b[r]-b[l-1];
int lma=lmax[l-1];
int lmi=lmin[l-1];
int rma=rmax[r+1];
int rmi=rmin[r+1];
if(r!=n) {
rma -= d;
rmi -= d;
}
int mi;
if(r!=n)
mi=min(lmi,rmi);
else mi=lmi;
int ma;
if(r!=n)
ma=max(lma,rma);
else ma=lma;
////// if(ma)ma=0;
////// if(mi==LLONG_MIN)mi=0;
// cout<<d<<' '<<mi<<' '<<ma<<endl;
// cout<<lmin[1]<<endl;
// cout<<lmi<<' '<<lma<<endl;
if(ma<0)ma=0;
if(mi>0)mi=0;
cout<<ma-mi+1<<endl;
}
}
return 0;
}
题意:给一个n和k,a排列是这样排列的,假如k=5,n为8排列就为1,2,3,4,5,4,3,2;8个元素,然后我们要求出一个p数组,映射关系为,$b[i]=p[a[i]]$,得到的b数组要求是逆序对要<=a序列的逆序对个数,且b数组的字典序最大,我们要求出p数组
思路:规律题,我们可以发现当我们这样排列时即可,k=5,n=8;末尾是5 4 3 2,前面是1,得到1 5 4 3 2,然后得到b数组,1 5 3 4 2 3 4 5 ,我们得到的符合条件
diamond:
#include<bits/stdc++.h>
using namespace std;
#define int long long
void solve(){
int n,k;
cin>>n>>k;
int hou=n-k+1;
int qian=k-hou;
for (int i = 1; i <=qian ; ++i) {
cout<<i<<' ';
}
while (hou--){
cout<<k--<<' ';
}
cout<<'\n';
}
int32_t main() {
int t;
cin>>t;
while (t--){
solve();
}
}
题意:给1个1到n的顺序列,我们要将这个数组变为n-1个1和一个2的序列,我们的操作是这样的,选择a[x],和a[y],将$a_x = \left\lceil \frac{a_x}{a_y} \right\rceil$,问至多操作n+5次,如何操作才能得到答案
思路:假设我们得到的是1到200000,我们对他开方得到,448,22,5,3,3因此我们对这些数分别这样操作,200000/448,得到448,然后/448,得到1,这样我们就得到了9次即可,然后我们加上n-8,这样我们就可以在n+5次之内得到答案
diamond:
#include "bits/stdc++.h"
#define endl '\n'
using namespace std;
void solve() {
vector<int>ve ;
map<int,int>mp;
int n;
cin >> n;
if (n == 3) {
cout << 2 << endl;
for (int i = 0; i < 2; i++) cout << 3 << " " << 2 << endl;
return;
}
int d = n;
while (d != 3){
ve.push_back(d);
mp[d]=1;
double g=(int)floor(sqrt(d)) + 1;
d=(int )g;
if(g*g==d*d);
else d++;
}
ve.push_back(3);
mp[3]=1;
cout<<n+ve.size()-2<<endl;
for(int i=4;i<=n;i++){
if(mp[i]!=1){
cout<<i<<" "<<n<<endl;
}
}
for (int i = 0; i <ve.size() ; ++i) {
if(ve[i]==3){
cout<<ve[i]<<' '<<2<<endl;
cout<<ve[i]<<' '<<2<<endl;
}
else {
cout << ve[i] << ' ' << ve[i + 1] << endl;
cout << ve[i] << ' ' << ve[i + 1] << endl;
}
}
}
signed main() {
int t;
cin >> t;
while (t--) solve();
}