目录
A. Tokitsukaze and All Zero Sequence
★B1. Tokitsukaze and Good 01-String (easy version)
★B2. Tokitsukaze and Good 01-String (hard version)
AC A. Everything Everywhere All But One
Day1
#790 Div4
rzt B. Equal Candies
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+10;
int a[51];
void solve()
{
int n,minx=1e7+10,res=0;
cin>>n;
for(int i=0;i<n;i++)
{
cin>>a[i];
minx=min(minx,a[i]);
}
for(int i=0;i<n;i++)
res+=a[i]-minx;
cout<<res<<endl;
}
signed main()
{
int t;
cin>>t;
while(t--)
solve();
return 0;
}
★C. Most Similar Words
题意:
思路:
把字符串存入二维数组里 string数组
两个两个比较 保留最小值
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+10;
string s[51];
void solve()
{
int n,m,t,res=0x3fffffff;
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>s[i];
for(int i=1;i<n;i++)
for(int j=i+1;j<=n;j++)
{
t=0;
for(int k=0;k<m;k++)
t+=abs(s[i][k]-s[j][k]);
res=min(res,t);
}
cout<<res<<endl;
}
signed main()
{
int t;
cin>>t;
while(t--)
solve();
return 0;
}
★D. X-Sum
题意:
思路:
某点的左斜对角线 i+j都相同
右斜对角线 i-j都相同 i-j+m(因为i-j可能是负数)
预处理左右对角线
然后枚举每个点 取最大的和
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+10;
int a[205][205];
int l[550],r[550];
void solve()
{
int n,m,res=0;
memset(l,0,sizeof l); //记得每次l r数组要清空
memset(r,0,sizeof r);
cin>>n>>m;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
cin>>a[i][j];
l[i+j]+=a[i][j]; //预处理左对角线
r[i-j+m]+=a[i][j]; //预处理右对角线 因为i-j可能是负数 所以+m
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
res=max(res,l[i+j]+r[i-j+m]-a[i][j]);
cout<<res<<endl;
}
signed main()
{
int t;
cin>>t;
while(t--)
solve();
return 0;
}
★E. Eating Queries
题意:
思路:
问每次最少吃多少糖 也就是从大到小排序
糖分越大 糖数越小 用二分查找糖分>x的位置
如果整个数组糖分之和都<x 则无解 输出-1
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=1.5e5+10;
int a[N],s[N];
bool cmp(int x,int y)
{
return x>y;
}
void solve()
{
int n,q,x;
cin>>n>>q;
for(int i=1;i<=n;i++) cin>>a[i];
sort(a+1,a+n+1,cmp);
for(int i=1;i<=n;i++)
s[i]=s[i-1]+a[i];
while(q--)
{
int x;
cin>>x;
int l=1,r=n;
int res=1;
if(s[r]<x)
{
cout<<-1<<endl;
continue;
}
while(l<r)
{
int mid=l+r>>1;
if(s[mid]>=x)r=mid;
else l=mid+1;
}
cout<<r<<endl;
}
}
signed main()
{
int t;
cin>>t;
while(t--)
solve();
return 0;
}
Day2
#789 Div2
A. Tokitsukaze and All Zero Sequence
题意:
思路:
找规律发现
如果序列里有一组重复元素 则操作数=数组长 这里重复元素的判断可以用set去重
如果序列里有0 则操作数=序列里非零元素的个数
如果序列既无0也不重复 则需要多1步把两元素同化为0的操作 也就是数组长+1
#include <iostream>
#include <algorithm>
#include <vector>
#include <cmath>
#include <map>
#include <set>
#define INF 0x3f3f3f3f
#define DINF 0xc0c0c0c0
#define ll long long
using namespace std;
const int N=2e5+10;
void solve()
{
int n,cnt=0,x;
set<int>s;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>x;
s.insert(x);
if(x!=0) cnt++;
}
if(n-cnt!=0) cout<<cnt<<endl;
else if(s.size()<n) cout<<n<<endl;
else cout<<1+n<<endl;
}
int main()
{
int t;
cin>>t;
while(t--)
{
solve();
}
}
★B1. Tokitsukaze and Good 01-String (easy version)
题意:
思路:
把字符串两个两个字符看作一组 如果组内元素不相同 则需要操作一次将其变为相同
比如 1110011000
可以看成11 10 01 10 00 所以操作数是3
#include <iostream>
using namespace std;
const int N=2e5+10;
void solve()
{
int n,cnt=0;
cin>>n;
string s;
cin>>s;
for(int i=1;i<n;i+=2)
if(s[i]!=s[i-1]) cnt++;
cout<<cnt<<endl;
}
int main()
{
int t;
cin>>t;
while(t--)
{
solve();
}
}
★B2. Tokitsukaze and Good 01-String (hard version)
题意:
这是B1问题的强化版,增强的地方就是需要求出在最少操作次数的基础上最少有多少段
#include <iostream>
#include <algorithm>
#include <vector>
#include <cmath>
#include <map>
#include <set>
#define INF 0x3f3f3f3f
#define DINF 0xc0c0c0c0
#define ll long long
using namespace std;
const int N=2e5+10;
void solve()
{
int n,cnt=0,res=0;
vector<char>v;
cin>>n;
string s;
cin>>s;
for(int i=1;i<n;i+=2)
if(s[i]!=s[i-1]) cnt++;
for(int i=1;i<n;i+=2)
if(s[i]==s[i-1]) v.push_back(s[i]);
res=unique(v.begin(),v.end())-v.begin();
res=max(res,1);
cout<<cnt<<' '<<res<<endl;
}
int main()
{
int t;
cin>>t;
while(t--)
{
solve();
}
}
Day3
#794 Div2
AC A. Everything Everywhere All But One
模拟法:
这块注意要把数据类型改成double 如果是int型 比如8/3=2 而样例中刚好有你删去的a[i]=2 这样影响判断
#include <iostream>
#include <algorithm>
#include <vector>
#include <cmath>
#include <map>
#include <set>
#define INF 0x3f3f3f3f
#define DINF 0xc0c0c0c0
//#define int long long
using namespace std;
const int N=1e5+10;
void solve()
{
int n;
double a[55];
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=n;i++)
{
double sum=0;
for(int j=1;j<=n;j++)
if(j!=i) sum+=a[j];
if(sum/(n-1)==a[i])
{
cout<<"YES"<<endl;
return;
}
}
cout<<"NO"<<endl;
}
signed main()
{
int t;
cin>>t;
while(t--)
{
solve();
}
}
推理法:
#include <iostream>
#include <algorithm>
#include <vector>
#include <cmath>
#include <map>
#include <set>
#define INF 0x3f3f3f3f
#define DINF 0xc0c0c0c0
//#define int long long
using namespace std;
const int N=1e5+10;
void solve()
{
int n,a[55],sum=0;
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i],sum+=a[i];
for(int i=1;i<=n;i++)
if(sum-a[i]==a[i]*(n-1))
{
cout<<"YES"<<endl;
return;
}
cout<<"NO"<<endl;
}
signed main()
{
int t;
cin>>t;
while(t--)
{
solve();
}
}
AC B. Odd Subarrays
题意:
思路:
通过样例发现规律—— 答案=逆序对个数
但要注意不能重复配对
#include <iostream>
#include <algorithm>
#include <vector>
#include <cmath>
#include <map>
#include <set>
#define INF 0x3f3f3f3f
#define DINF 0xc0c0c0c0
//#define int long long
using namespace std;
const int N=1e5+10;
void solve()
{
int n,a[N],cnt=0;
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=n-1;i++)
{
if(a[i]>a[i+1]) cnt++,i++; //防止重复配对
}
cout<<cnt<<endl;
}
signed main()
{
int t;
cin>>t;
while(t--)
{
solve();
}
}
★C. Circular Local MiniMax
思路:
发现奇数个都不行 直接输出NO
偶数个情况 只要升序排列分成 前n/2 和 后n/2 间隔输出就能满足题意
再依次检查是否满足题目要求 不满足直接输出NO
#include <iostream>
#include <algorithm>
#include <vector>
#include <cmath>
#include <map>
#include <set>
#define INF 0x3f3f3f3f
#define DINF 0xc0c0c0c0
//#define int long long
using namespace std;
const int N=1e5+10;
void solve()
{
int n,a[N],b[N],t=1;
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
if(n%2)
{
cout<<"NO"<<endl;
return;
}
sort(a+1,a+n+1);
for(int i=1;i<=n;i+=2)
b[i]=a[t++];
for(int i=2;i<=n;i+=2)
b[i]=a[t++];
for(int i=2;i<n;i+=2)
if(b[i-1]>=b[i]||b[i+1]>=b[i])
{
cout<<"NO"<<endl;
return;
}
cout<<"YES"<<endl;
for(int i=1;i<=n;i++)
cout<<b[i]<<' ';
cout<<endl;
}
signed main()
{
int t;
cin>>t;
while(t--)
{
solve();
}
}
Day4
#793 Div2
★A. Palindromic Indices
题意:
思路:
发现只要统计中间重复字符个数即可
比如abaaaaba 则折半查找 分奇偶情况讨论
n&1 如果n是奇数=1 如果n是偶数=0
#include <iostream>
#include <algorithm>
#include <stack>
#include <cmath>
#include <map>
#include <set>
#define INF 0x3f3f3f3f
#define DINF 0xc0c0c0c0
#define int long long
using namespace std;
const int N=1e5+10;
void solve()
{
int n,cnt=0;
string s;
cin>>n>>s;
for(int i=(n-1)/2;i>=0;i--)
if(s[i]==s[(n-1)/2]) cnt++;
else break;
cout<<2*cnt-(n&1)<<endl;
}
signed main()
{
int t;
cin>>t;
while(t--)
{
solve();
}
}
★B. AND Sorting
思路:
& 运算特性:一个数进行&运算的话,一定是越来越小的
-1&n=n
#include <iostream>
#include <algorithm>
#include <stack>
#include <cmath>
#include <map>
#include <set>
#define INF 0x3f3f3f3f
#define DINF 0xc0c0c0c0
#define int long long
using namespace std;
const int N=2e5+10;
void solve()
{
int n,a[N],x=-1;
cin>>n;
for(int i=0;i<n;i++)
{
cin>>a[i];
if(a[i]!=i) x&=a[i];
}
cout<<x<<endl;
}
signed main()
{
int t;
cin>>t;
while(t--)
{
solve();
}
}
★C. LIS or Reverse LIS?
题意:
思路:
要想让LIS值最大 则需要形成一个上升下降序列
这样翻转与否LIS值都是最大
#include <iostream>
#include <algorithm>
#include <stack>
#include <cmath>
#include <map>
#include <set>
#define INF 0x3f3f3f3f
#define DINF 0xc0c0c0c0
#define int long long
using namespace std;
const int N=2e5+10;
void solve()
{
int n,cnt=0,x;
cin>>n;
map<int,int>mp;
for(int i=0;i<n;i++)
{
cin>>x;
mp[x]++;
if(mp[x]<=2) cnt++;
}
cout<<(cnt+1)/2<<endl; //+1防止序列只有一个元素情况
}
signed main()
{
int t;
cin>>t;
while(t--)
{
solve();
}
}