星期一每日三题:
A 题:
题意:n个积木柱,每个柱子有hi块积木,每次能移除高度h以上的积木,单次限制条件为移除总积木数不超过k(k给出,h任意),要使所有积木等高,问最少移除多少次。
思路:贪心,前缀和。先排序,然后经过一番处理(较为繁琐),得出下标为高度的需移除积木数的后缀和数组。开始我想着用二分找移除高度,后来t了,想了下其实没必要,就从高到0遍历了一遍高度,得出了移除次数。虽然感觉并不难,但写了半天代码。。
代码如下:
#include <bits/stdc++.h>
using namespace std;
using ll=long long;
using PII=pair<int,int>;
const int N=2e5+10;
int n,k;
int h[N];
int cnt1[N];
ll cnt[N],ans;
void solve(){
cin >> n >> k;
for(int i=1;i<=n;i++){
cin >> h[i];
}
if(n==1){cout << 0; return ;}
sort(h+1,h+n+1,greater<int>());
if(h[1]==h[n]){cout << 0; return ;}
for(int i=1;i<=n;i++){
h[i]=h[i]-h[n];
}
for(int i=1;i<=n;i++){
cnt1[h[i]]=i;
}
cnt[h[1]]=cnt1[h[1]];int kk=cnt[h[1]];
for(int i=h[1]-1;i;i--){
if(cnt1[i]==0) cnt[i]=cnt[i+1]+kk;
else kk=cnt1[i],cnt[i]=cnt[i+1]+kk;
}
ll tmp=0;
for(int i=h[1];i;i--){
if(tmp+k<cnt[i-1]) tmp=cnt[i],ans++;
}
cout << ans+1;
}
int main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int t=1;
//cin >> t;
while(t--) solve();
return 0;
}
//make it count
//开ll plz
周二比赛:
A题:之前做过,不讲了.
B题:
题意:给出长度为n序列,要求输出n/2个不同数对,满足三个条件,一x!=y,二x,y是a中的数,三x模y不能在a中.
思路:根据条件一三,得x必须严格大于y.刚开始想的是开个筛子数组,出现过的数都标记一下,然后以on²的复杂度挨个找,找到n/2个数对就break,但tle.后来发现x%y的结果一定是严格小于y的,并且数对 数量也不多,只需n/2个,那么可以用on的复杂度,用每个数和a中最小数进行判断.
代码如下:
#include <bits/stdc++.h>
using namespace std;
using ll=long long;
using PII=pair<int,int>;
const int N=2e5+10;
int n;
int a[N];
int cnt;
void solve(){
cnt=0;
cin >> n;
for(int i=1;i<=n;i++){
cin >> a[i];
}
sort(a+1,a+n+1);
for(int i=2;i<=n;i++){
if(a[i]!=a[i-1]) cout << a[i] << " " << a[1] << endl;
cnt++;
if(cnt==n/2) break;
}
}
int main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int t=1;
cin >> t;
while(t--) solve();
return 0;
}
//make it count
//开ll plz
星期三每日三题:
A题:
题意:自行理解
思路:无需多言
代码如下:
#include <bits/stdc++.h>
using namespace std;
using ll=long long;
using PII=pair<int,int>;
const int N=3e5+10;
int n,m,minn;
int a[N],b[N];
ll suma,sumb;
ll tmpa,tmpb;
int ans;
void solve(){
cin >> n;
for(int i=1;i<=n;i++){
cin >> a[i];
suma+=a[i];
}
cin >> m;
for(int i=1;i<=m;i++){
cin >> b[i];
sumb+=b[i];
}
if(suma!=sumb){cout << -1; return ;}
minn=min(n,m);
for(int idxa=1,idxb=1;idxa<=n;){
tmpa+=a[idxa++],tmpb+=b[idxb++];
while(tmpa!=tmpb){
if(tmpa>tmpb) tmpb+=b[idxb++];
else tmpa+=a[idxa++];
}
ans++,tmpa=0,tmpb=0;
}
cout << ans;
}
int main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int t=1;
//cin >> t;
while(t--) solve();
return 0;
}
//make it count
//开ll plz
B题:
题意:抓鼠鼠,有n个房间,每个房间放陷阱的代价是ci,有一a数组,老鼠每秒从i房间跑到a[i]房间(i.e.从a[i]房间跑到a[a[i]]房间),不知道老鼠初始在哪个房间,问最小布置陷阱代价,确保一定能捉住老鼠。
思路: 感觉很有意思的一道题,最开始想到的是并查集,但因为太久没写并查集所以去网上看,还有用图写的,打算图和并查集的写法都做一遍.
老鼠的路线有四种可能性,单点,链,环,链和环相连.链就在最后一点放陷阱,后两种在环中代价最小处放陷阱.
代码1如下:
#include <bits/stdc++.h>
using namespace std;
using ll=long long;
using PII=pair<int,int>;
const int N=2e5+10;
int n;
int c[N],a[N],vi[N];
ll ans;
void solve(){
cin >> n;
for(int i=1;i<=n;i++){
cin >> c[i];
}
for(int i=1;i<=n;i++){
cin >> a[i];
}
for(int i=1;i<=n;i++){
int x=i;
while(!vi[x]){
vi[x]=i;
x=a[x];
}
if(vi[x]!=i) continue;
int cc=c[x],tmp=a[x];
while(tmp!=x){
cc=min(c[tmp],cc);
tmp=a[tmp];
}
ans+=cc;
}
cout << ans;
}
int main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int t=1;
//cin >> t;
while(t--) solve();
return 0;
}
//make it count
//开ll plz
星期五打了个比赛,打麻了,脑子不知道在想什么,手不知道在敲什么。
星期六打了个比赛,a了俩道,其中一道纯纯签到题。
另一道:
题意:题面有点恶心,大意为给一算式,输出其结果奇偶性,然后m次输入x,y,把第x个数改为y,输出修改后结果奇偶性(修改保留)。
思路:有点繁琐,自己看代码。
代码如下:
#include <bits/stdc++.h>
using namespace std;
using ll=long long;
using PII=pair<int,int>;
const int N=1e5+10;
int n,m;
char op[N];
int a[N];
bool vi[N];
vector<int>ve;
int res;
bool ans;
void solve(){
cin >> n >> m;
for(int i=1;i<=n;i++){
int tmp;char c;
cin >> tmp;
if(tmp&1) a[i]=1,vi[i]=1;
else a[i]=0,vi[i]=0;
if(i==n) break;
cin >> c;
op[i]=c;
}
int cnt=0;
for(int i=1;i<n;i++){
if(op[i]!='*'){
if(!(a[i]&1)) cnt++;
ve.push_back(cnt);
a[i]=ve.size()-1;
cnt=0;
}else{
while(op[i]=='*'){
if(!(a[i]&1)) cnt++;
a[i]=ve.size();
i++;
}
if(!(a[i]&1)) cnt++;
ve.push_back(cnt);
a[i]=ve.size()-1;
cnt=0;
}
}
if(op[n-1]=='*'){
a[n]=ve.size()-1;
}else{
if(a[n]&1) ve.push_back(0);
else ve.push_back(1);
a[n]=ve.size()-1;
}
// for(int i=1;i<=n;i++) cout << a[i] << " ";cout << endl;
for(auto i:ve){
// cout << i;
if(i==0) res++;
}
if(res&1) ans=1;
else ans=0;
if(ans) cout << "odd" << endl;
else cout << "even" << endl;
while(m--){
int x,y;
cin >> x >> y;
if(y&1 && vi[x]==0){
vi[x]=1;
ve[a[x]]--;
if(ve[a[x]]==0) res++;
if(res&1) ans=1;
else ans=0;
}else if(!(y&1) && vi[x]==1){
vi[x]=0;
if(ve[a[x]]==0) res--;
ve[a[x]]++;
if(res&1) ans=1;
else ans=0;
}
if(ans) cout << "odd" << endl;
else cout << "even" << endl;
}
}
int main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int t=1;
//cin >> t;
while(t--) solve();
return 0;
}
//make it count
//开ll plz