#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 10;
int t,k,n,x,cnt;
int main(){
cin >> t;
while(t--){
cnt = 1;
cin >> n >> k;
vector < pair <int,int> > v(n);
for(int i = 0;i < n;i++) cin >> v[i].first,v[i].second = i;
sort(v.begin(),v.end());
for(int i = 0;i < n - 1;i++)
if(v[i].second + 1 != v[i + 1].second)
cnt++;
if(cnt <= k) cout << "YES\n";
else cout << "NO\n";
}
return 0;
}
这个题一开始想的太简单了,只考虑到了位置不对的数组,但是如果像1 4 2这样的,位置不对的只有两个,但是必须需要分成三组才能从小到大 1 4 和2 1 和2 4都不行 因为1就插不到里面去。所以我们需要将每个数的位置记一下,然后按从小到大进行一个排序,排序之后一个个对比,如果前一个数没有和后一个数在之前的序列中是连续的,那么这两个就必须要分开,这是为了给中间留个位置 比如1 2 7 5 不能把1 2 7分成一组,这样5就进不来了。只要最后分的次数小于等于k了,那么就输出yes。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e4 + 10;
int n,cnt,arr[maxn],pos;
int main(){
cin >> n;
for(int i = 0;i < n;i++){
cin >> arr[i];
if((int)abs(arr[i]) % 2 == 1) cnt++;
}
pos = 1;
for(int i = 0;i < n;i++){
if(arr[i] % 2 == 0) cout << arr[i] / 2 <<'\n';
else{
if(pos++ <= cnt / 2) cout << (int)floor(arr[i] * 1.0 / 2) <<'\n';
else cout << (int)ceil(arr[i] * 1.0 / 2) << '\n';
}
}
return 0;
}
b
i
b_i
bi =
a
i
2
\frac{a_i}2
2ai + x
因为
∑
i
=
1
n
b
i
\sum_{i\;=\;1}^nb_i
∑i=1nbi = 0,
∑
i
=
1
n
a
i
\sum_{i\;=\;1}^na_i
∑i=1nai = 0 x的取值只能为
1
2
\frac1 2
21或
−
1
2
-\frac1 2
−21 所以所有的x的和要为0,即一半为正的一半为负的,即有一半奇数要向上取整,有一半奇数要向下取整
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 10;
int n,a[maxn],b[maxn],pos[maxn],c[maxn],ans,Max;
int main(){
cin >> n;
for(int i = 1;i <= n;i++) cin >> a[i];
for(int i = 1;i <= n;i++) cin >> b[i];
for(int i = 1;i <= n;i++) pos[b[i]] = i;
for(int i = 1;i <= n;i++) c[i] = pos[a[i]];
ans = 0,Max = -1;
for(int i = 1;i <= n;i++){
if(c[i] > Max) Max = c[i];
else ans++;
}
cout << ans << '\n';
return 0;
}
我们知道了一开始的序列和最后的序列,我们需要找到每一辆车他所移动之后的位置,比如3 5 1 2 4 变成了 4 3 1 5 2 车3从最开始的位置变到了第二个位置 它所在的位置就为2,所以就能得到这么一个序列2 4 3 5 1,指的是每辆车变化之后的位置。为什么要这样一个序列呢,首先3车是最先进去的,而出来后却不在第一个位置而是在第二个位置,所以如果要是它后面的车进去出来之后却在它的位置前面,说明这辆车超车了。车3 5的位置变成了2 4是正常的,因为车5并没有超过车3,而这个时候第三个进去的车1的位置却到了第二个进去的车5的前面去了,说明它超车了,这个第四个进去的车2变到了第五个位置,没有超过前面的车5是对的,但第五个位置已经是最后了,在车2后面的车4必定超车了。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int n,m;
const int mod = 1e9 + 7;
ll power(ll a,ll b){
a %= mod;
ll res = 1;
while(b > 0){
if(b & 1) res *=a % mod;
a *= a % mod;
b >>= 1;
}
return res;
}
int main(){
cin >> n >> m;
cout << power(power(2,m) - 1,n);
return 0;
}
以后所有用次方的地方都要自己写一个快速幂出来,不然就会超时。快速幂一个礼物三个盒子的可以放1 放2 放3 放1 2 放1 3 放2 3 放1 2 3但是不能不放,也就是3的真子集去掉了空集, 2 m − 1 {2^m} - 1 2m−1种情况,而第二件礼物和第一件礼物完全不冲突,也有 2 m − 1 {2^m} - 1 2m−1种情况,所以n个礼物就有 ( 2 m − 1 ) n ({2^m} - 1)^n (2m−1)n种情况。快速幂背一下板子就好了,记住用法快速打出来
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll odd,eve,n,m,t,x,ans;
int main(){
cin >> t;
while(t--){
cin >> n;
odd = eve = ans = 0;
for(int i = 0;i < n;i++){
cin >> x;
if(x % 2 == 0) eve++;
else odd++;
}
cin >> m;
for(int i = 0;i < m;i++){
cin >> x;
if(x % 2 == 0) ans += eve;
else ans += odd;
}
cout << ans << '\n';
}
}
这个题很简单,并不需要每一个相减那样会超时的,只需要找一下偶数和奇数截距就好,写到博客里并不是写思路,一定要一定要看清楚数据范围,又忘记开longlong了,一交就wa
#include<bits/stdc++.h>
using namespace std;
string s;
int t,n,odd,eve,bad,odds,eves;
int main(){
cin >> t;
while(t--){
odd = eve = bad = 0;
cin >> n;
for(int i = 0;i < n;i++){
cin >> s;odds = eves = 0;
int len = (int)s.size();
if(len % 2 == 1) odd++;
else{
eve++;
for(int j = 0;j < len;j++){
if(s[j] == '1') odds++;
else eves++;
}
//cout << odds << ' ' << eves << '\n';
if(odds % 2 == 1 || eves % 2 == 1) bad++;
// cout << bad << '\n';
}
}
if(bad % 2 == 1 && odd == 0) cout << n - 1 << '\n';
else cout << n << '\n';
}
return 0;
}
如果是长度为奇数的串的话,那么不管有几个0和几个1都能重新排列成回文串,如果长度为偶数的话,就要分为两种情况,如果1和0的个数为偶数的话,那么就可以重新排列成回文串。但如果为奇数的话,那么就不可以,这个时候就需要找其他的串就交换1和0了。首先就是找长度为奇数的串,因为长度为奇数的串不管交换掉其中的哪一个也仍为回文串,这时候就可以将坏串中的奇数个数的0或1转换成1或0变成偶数了。或者两个坏串之间相互交换,因为他们都是奇数个数的0和1,相加后都是偶数个数的0和1这个时候重新分配后就可以变成回文串了。所以如果没有奇数串但又有奇数个数的坏串的时候,就会有n-1个回文串,其他情况均为n个回文串
#include<bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
map <int,int> m;
vector <int> v;
int t,n,k,d,minn,cnt;
int main(){
cin >> t;
while(t--){
minn = INF;cnt = 0;
m.clear(),v.clear();
cin >> n >> k >> d;
for(int i = 0;i < n;i++){
cin >> k;
v.push_back(k);
}
for(int i = 0;i < d;i++){
if(!m[v[i]]) cnt++;
m[v[i]]++;
}
minn = cnt;
for(int i = d;i < n;i++){
m[v[i - d]]--;
if(!m[v[i - d]]) cnt--;
if(!m[v[i]]) cnt++;
m[v[i]]++;
// cout << cnt << " " << minn << '\n';
if(cnt < minn) minn = cnt;
}
cout << minn << '\n';
}
}
数据范围比较大,不能通过暴力的去解。我们首先用一个vector来存数据,这样比较节省空间,虽然有k个节目,但是真正能用到的可能没有k个,所以也是为了节省空间我开了map。一开始我们将前d天的节目存下来,如果存之前这个m为0了,就让cnt++意思是这d天内有一个新节目。之后从第d+1天开始,每天减去d天前的一个节目,如果减去这个节目后m为0了,就说明这d天之内都没有这个节目了。再加上第d+1天的节目。每次用cnt和minn比较,找到所有区间里面cnt最小的一个。
#include<bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
int t,n,x,minn,cnt;
void no(){
cout << -1 << '\n';
}
int main(){
cin >> t;
while(t--){
cin >> n;
vector < vector < int > > v(n, vector < int > ());
minn = INF;
for(int i = 0;i < n;i++){
cin >> x;v[x - 1].push_back(i);
}
if(n == 1){
no();
continue;
}
for(int i = 0;i < n;i++){
if(v[i].empty()) continue;
for(int j = 0;j < (int)v[i].size() - 1;j++){
cnt = v[i][j + 1] - v[i][j] + 1;
if(cnt < minn) minn = cnt;
}
}
if(minn == INF){
no();
continue;
}
cout << minn << '\n';
}
return 0;
}
这个题的思路很简单。但是vector的嵌套还是用不熟难受。首先vector的嵌套要写成这样:vector < vector < int > > v(N,vector < int > () ) 里面一定是多一个括号的。其次就是每次要是需要清空vector的话,在v里用clear只能清空vector的大容器,而vector的小容器是没有任何变化的。我们最好是在每次循环的时候重新定义vector,这个题要么用stable_sort排个稳定的序,依次找相同元素的所在位置的最小差,如果minn没有变化说明所有的元素都只出现了1次,输出-1.要么就用vector做,每次将相同元素的位置添加到vector里面,后面遍历一遍vector找最小就好,很简单的一道题主要是卡死在vector上面了。