这场比赛打完之后…心态爆炸…熬夜打比赛打到凌晨3:00…比赛中A掉了4道题…结果system test测完后…C题瞎糊的算法T掉了,D题因为某个小细节…炸掉了…结果只有1600+名…
rating-=100
目前rating:1720…(上次刚打上去这次掉下来,好憋屈qwq)
A. Diversity
题意:给你一串只由小写字母组成的字符串,问你最少改几个字母(随意替换),可以使这个字符串有不少于 k 个不同的字符,如果无论怎么改都不可能做到,输出
impossible 。
思路&&题解:首先,很显然,如果k大于字符串长度,是绝对不可能做到的,直接输出 impossible 就行了。其余情况只要扫一遍字符串长度,统计一下已经有几个不一样的字符 tot ,之后输出 max(0,k−tot) 就行了。
代码如下:
#include<bits/stdc++.h>
using namespace std;
bool book[26];
int tot=0;
string s;
int k;
int main() {
cin>>s>>k;
if(s.length()<k) {
puts("impossible");
return 0;
}
for(int i=0;i<s.length();i++) {
if(!book[s[i]-'a']) {
book[s[i]-'a']=1;
tot++;
}
}
if(tot>=k) {
puts("0");
return 0;
}
else {
printf("%d\n",k-tot);
return 0;
}
return 0;
}
B. Rectangles
题意:给你一个 n×m 的 01 矩阵,其中每个元素都由 0 或者
1 组成,要求你在其中找出非空子集,使它满足下面两个性质:
1. 子集里所有数全为 0 全为1 ;
2. 子集里任意两个数都在同一行或者同一列。
求一共有多少满足的子集。
思路&&题解:由性质 2 可以很快得到,子集中的所有元素必须都在同一行或同一列。于是可以用两个bitset 分别存行和列的元素值,这样用 bitset 的 count 函数可以很快得到 1 的个数,0 的个数的话只要减一下就行了。之后就是跟组合数有关的了,对于组合数我们可以预处理,而每行的答案就是 ∑cnt0i=1(cnt0i)+∑cnt1i=1(cnt1i) 了,然后计算一下就行了。
代码如下:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int mp[55][55];
ll C[55][55];
bitset<55> b[55],c[55];
ll sum=0;
int n,m;
void init() {
for(int i=0;i<=50;i++)
C[i][0]=C[i][i]=1;
for(int i=1;i<=50;i++) {
for(int j=1;j<i;j++) {
C[i][j]=C[i-1][j-1]+C[i-1][j];
}
}
}
int main() {
init();
cin>>n>>m;
for(int i=1;i<=n;i++) {
for(int j=1;j<=m;j++) {
cin>>mp[i][j];
b[i][j]=mp[i][j];
c[j][i]=mp[i][j];
}
}
sum=(ll)n*m;
for(int i=1;i<=n;i++) {
int tmp=b[i].count();
ll tot=0;
for(int j=2;j<=tmp;j++)
tot+=C[tmp][j];
for(int j=2;j<=m-tmp;j++)
tot+=C[m-tmp][j];
sum+=tot;
}
for(int i=1;i<=m;i++) {
int tmp=c[i].count();
ll tot=0;
for(int j=2;j<=tmp;j++)
tot+=C[tmp][j];
for(int j=2;j<=n-tmp;j++)
tot+=C[n-tmp][j];
sum+=tot;
}
cout<<sum<<endl;
}
C. Sorting by Subsequences
题意:给你一个长度为 n 的无序数组,让你将它分为几个子序列,将每个序列排序一遍(不改变他们在原数组中的位置),使该数组重新有序。求最多可分成几个子序列。
思路&&题解:其实这题就是让你找原数组与排序后的数组中位置上的循环有几个(差不多这意思吧讲不清qwq)…
代码如下:
#include<bits/stdc++.h>
using namespace std;
const int maxn=100050;
int n;
struct node {
int x,id;
}a[maxn];
struct ans {
int num;
vector<int> arr;
}ask[maxn];
int tot=0;
int cnt=0,pos=1;
bool vis[maxn];
bool cmp(node a,node b) {
return a.x<b.x;
}
int main() {
cin>>n;
for(int i=1;i<=n;i++) {
cin>>a[i].x;
a[i].id=i;
}
sort(a+1,a+n+1,cmp);
for(int i=1;i<=n;i++) {
if(!vis[i]) {
pos=i;
tot++;
while(!vis[pos]) {
ask[tot].arr.push_back(a[pos].id);
ask[tot].num++;
cnt++;
vis[pos]=1;
pos=a[pos].id;
}
}
}
cout<<tot<<endl;
for(int i=1;i<=tot;i++) {
cout<<ask[i].num<<" ";
sort(ask[i].arr.begin(),ask[i].arr.end());
for(int j=0;j<ask[i].num;j++)
cout<<ask[i].arr[j]<<" ";
cout<<'\n';
}
return 0;
}
比赛时候我找循环时是每次从
1 开始找第一个 vis[i]=0 的,所以会 TLE …
D. Interactive LowerBound
P.S.这是一道交互题(我之前从来没做过啊喂…qwq)
题意:给你一个已经排好序的链表,给定链表长度为 n ,最小的数在第
st 个位置,给定一个 k ,让你在小于等于1999 次询问内确定比 k 大的最小的数。规定每次输出有两种可能:
1: ? x,表示询问第 x 位的数值和比第一个他大的元素的位置。
2: ! x,表示确定题目中符合给定的数值为 x 并退出程序。
每次输出后均要flush 一遍。
思路&&题解:先随机 1000 次,第一次固定询问最小的那个元素,即? st。然后用随机种子 rand 出999次,并询问该位置。如果最小的元素数值大于等于 k ,那么直接输出该数值就行了。之后从这1000次询问中挑出小于k 的最大值往上暴力找到第一个大于等于 k <script type="math/tex" id="MathJax-Element-3425">k</script>的就行了。
代码如下:
#include<bits/stdc++.h>
#define F fflush(stdout)
using namespace std;
const int maxn=50050;
typedef pair<int,int> pii;
pii now;
int val[maxn],nxt[maxn],pos[maxn];
int n,st,k;
inline pii que(const int& x) {
printf("? %d\n",x),F;
pii now;
scanf("%d%d",&now.first,&now.second);
return now;
}
inline void pri(const int& x) {
printf("! %d\n",x),F;
exit(0);
}
int main() {
srand(unsigned((long long)new char));
scanf("%d%d%d",&n,&st,&k);
now=que(st);
pos[1]=st;
val[1]=now.first;
nxt[1]=now.second;
if(now.first>=k)
pri(now.first);
for(int i=2;i<=1000;i++) {
int tmp=(rand()*(rand()+rand())%n*rand())%n+1;
pos[i]=tmp;
now=que(tmp);
val[i]=now.first;
nxt[i]=now.second;
}
int maxindex=1;
for(int i=2;i<=1000;i++)
if(val[i]>val[maxindex]&&val[i]<k)
maxindex=i;
int nowpos=pos[maxindex],nextpos=nxt[maxindex],value=val[maxindex];
while(value<k) {
if(nextpos==-1)
pri(-1);
nowpos=nextpos;
now=que(nowpos);
value=now.first;
nextpos=now.second;
}
pri(value);
return 0;
}
E. Upgrading Tree
暂时还没写..先放一放..