文章目录
A. Square String?
#include<bits/stdc++.h>
using namespace std;
int main(){
int t;
cin>>t;
while(t--){
string s;
cin>>s;
if(s.size()%2==1){
cout<<"NO"<<endl;
continue;
}
int flag=0;
for( int i=0;i<s.size()/2;i++){
if(s[i]!=s[s.size()/2+i]) flag=1;
}
if(flag==0){
cout<<"YES"<<endl;
}
else cout<<"NO"<<endl;
}
}
B. Squares and Cubes
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main(){
int t;
cin>>t;
while(t--){
ll n;
cin>>n;
set<ll>se;
for( ll i=1;i*i*i<=n;i++){
se.insert(i*i*i);
}
for( ll i=1;i*i<=n;i++){
se.insert(i*i);
}
cout<<se.size()<<endl;
}
return 0;
}
C. Wrong Addition
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main(){
int t;
cin>>t;
while(t--){
ll a,s;
cin>>a>>s;
string ans;
int flag=0;
while(s&&a){
if(s%10>=a%10){
ans+='0'+s%10-a%10;
s/=10;
a/=10;
}
else if(s%10<a%10){
ll ss=s%100;
if(s%100-a%10>=10||s%100-a%10<0) {
flag=1;
break;
}
ans+='0'+s%100-a%10;
a/=10;
s/=100;
}
}
while(s){
ans+=s%10+'0';
s/=10;
}
if(a) flag=1;
reverse(ans.begin(),ans.end());
ll x=0;
for( int i=0;i<ans.size();i++){
x=x*10+ans[i]-'0';
}
if(flag) cout<<"-1"<<endl;
else cout<<x<<endl;
}
return 0;
}
D. New Year’s Problem
二分法。
首先二分答案,然后设计check函数
由于题中有一个条件最多选择n-1个商店,所以如果选择商品数大于选择商店数,题目就成立。
#include <bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;
int solve(){
int n,k;
cin>>n>>k;
vector<vector<int>>v(n,vector<int>(k));
multiset<pair<int,int>>se[k+1];
for( int i=0;i<n;i++){
for( int j=0;j<k;j++){
cin>>v[i][j];
}
}
auto check=[&] (int x){
vector<int>joyed(k);
int cnt=0;
for( int i=0;i<n;i++){
int flag=0;
for( int j=0;j<k;j++){
if(v[i][j]>=x) joyed[j]++,flag=1;
}
if(flag) cnt++;
}
for( int i=0;i<k;i++) if(joyed[i]==0) return 0;
int sum=accumulate(joyed.begin(),joyed.end(),0);
if(sum>cnt) return 1;
else return 0;
};
int l=0,r=1e9;
while(l<r){
int mid=(l+r+1)>>1;
// cout<<mid<<" "<<check(mid)<<endl;
if((!check(mid))<1) l=mid;
else r=mid-1;
}
return l;
}
int main() {
int t;
cin>>t;
while(t--){
cout<<solve()<<endl;
}
}
E. MEX and Increments
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=200100;
int w[N],cnt[N];
int main(){
int t;
cin>>t;
while(t--){
int n;
cin>>n;
multiset<int>se;
memset(cnt,0,sizeof(int)*(n+10));
for( int i=0;i<n;i++){
scanf("%d",&w[i]);
cnt[w[i]]++;
}
sort(w,w+n);
ll sum=0;
int flag=0;//当flag==1时全部是-1
for( int i=0;i<=n;i++){
if(flag){
printf("-1 ");
continue;
}
if(cnt[i]==0) {
printf("%lld ",sum);
if(se.size()==0){
flag=1;
continue;
}
multiset<int> ::iterator it=--se.end();
if(*it>i) {
flag=1;
continue;
}
else{
sum+=i-*it;
se.erase(--se.end());
}
}
else {
// sum+=cnt[i];
printf("%lld ",sum+cnt[i]);
for( int j=0;j<cnt[i]-1;j++){
se.insert(i);
}
}
}
printf("\n");
}
return 0;
}
F. Let’s Play the Hat?
暴力+贪心
每次取b最小的几个人,放在人多的桌子上玩
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=200100;
int w[N],cnt[N];
struct p{
int cnt,id;
} b[N];
int cmp( p a,p b){
return a.cnt<b.cnt;
}
int main(){
int t;
cin>>t;
while(t--){
int n,m,k;
scanf("%d%d%d",&n,&m,&k);
memset(b,0,(n+10)*sizeof(int));
int low=n/m,high=n/m+(bool)(n%m);
for( int i=1;i<=n;i++){
b[i].id=i;
b[i].cnt=0;
}
// cout<<low<<" "<<high<<"??"<<endl;
if(low==high)
{
for( int i=1;i<=k;i++){
int cnt=1;
for( int j=1;j<=m;j++){
printf("%d ",low);
for( int pp=1;pp<=low;pp++) printf("%d ",cnt++);
}
printf("\n");
}
}
else
{
int chigh=n-m*low;
int clow=m-chigh;
for( int i=1;i<=k;i++){
sort(b+1,b+1+n,cmp);
int idx=1;
for( int j=1;j<=m;j++){
if(j<=chigh) {
printf("%d ",high);
for( int pp=1;pp<=high;pp++) {
printf("%d ",b[idx++].id );
b[idx-1].cnt++;
}
printf("\n");
}
else{
printf("%d ",low);
for( int pp=1;pp<=low;pp++){
printf("%d ",b[idx++].id );
}
printf("\n");
}
}
}
}
printf("\n");
}
return 0;
}
G
并查集
#include <bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;
struct dsu
{
const int n;
vector<int>a;
dsu( int n):n(n+1),a(n+1){
for( int i=0;i<n+1;i++) a[i]=i;
}
//y向x合并
void unite(int x, int y) {
a[find(y)] = find(x);
}
int find(int u) {
return a[u] == u ? a[u] : a[u] = find(a[u]);
}
};
int solve(){
int n,k;
int ans=0;
cin>>n>>k;
vector<array<int,4> >mine(n);
vector<int>t(n);
dsu d(n);
for( int i=0;i<n;i++){
for( int j=0;j<3;j++) cin>>mine[i][j];
mine[i][3]=i;
t[i]=mine[i][2];
}
auto cmp1=[&](array<int,4> a,array<int,4> b){
if(a[0]!=b[0]) return a[0]<b[0];
else return a[1]<b[1];
};
sort(mine.begin(),mine.end(),cmp1);
for( int i=1;i<n;i++){
if(mine[i][0]==mine[i-1][0]&&mine[i][1]-mine[i-1][1]<=k){
//cout<<mine[i-1][1]-mine[i][1]<<endl;
int x=mine[i][3],y=mine[i-1][3];
x=d.find(x),y=d.find(y);
t[x]=min(t[x],t[y]);
d.unite(x,y);
}
}
auto cmp2=[&](array<int,4> a,array<int,4> b){
if(a[1]!=b[1]) return a[1]<b[1];
else return a[0]<b[0];
};
sort(mine.begin(),mine.end(),cmp2);
for( int i=1;i<n;i++){
if(mine[i][1]==mine[i-1][1]&&mine[i][0]-mine[i-1][0]<=k){
int x=mine[i][3],y=mine[i-1][3];
x=d.find(x),y=d.find(y);
t[x]=min(t[x],t[y]);
d.unite(x,y);
}
}
multiset<int>se;
for( int i=0;i<n;i++){
if(d.find(i)==i) {
se.insert(t[i]);
}
}
// for( int i=0;i<v.size();i++){
// cout<<v[i].first<<v[i].second<<endl;
// }
for( int i=0;i<=200000;i++){
while(!se.empty()&&*se.begin()==i) se.erase(se.begin());
if(i+1>=se.size()) return i;
}
return -1;
}
int main() {
int t;
cin>>t;
while(t--){
cout<<solve()<<endl;
}
}
H. Permutation and Queries
分块算法
由于数列是一个全排列,因此一个点只有唯一的父节点和子节点。
取分块大小为sqrt(n),预处理所有数值跳过一整块的下一个结点。
每次更新,暴力更新前一块和后一块的所有值。
复杂度为(nlogn)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=100100;
int p[N],child[N];
const int sq=300;
int jump[N];
void update(int x){
int y=x,z=x;
for( int i=1;i<=sq;i++) y=p[y];
for( int i=1;i<=sq;i++) jump[z]=y,z=p[z],y=p[y];
y=x,z=x;
for( int i=1;i<=sq;i++) y=child[y];
for( int i=1;i<=sq;i++) jump[y]=z,z=p[z],y=p[y];
}
int main(){
int n,q;
cin>>n>>q;
for( int i=1;i<=n;i++){
scanf("%d",&p[i]);
child[p[i]]=i;
}
for( int i=1;i<=n;i++){
int x=i;
for( int j=1;j<=sq;j++){
x=p[x];
}
jump[i]=x;
}
while(q--){
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
if(a==1){
swap(child[p[b]],child[p[c]]);
swap(p[b],p[c]);
update(b);
update(c);
}
else{
while(c>=sq){
b=jump[b];
c-=sq;
}
while(c--){
b=p[b];
}
printf("%d\n",b );
}
}
}