A. Escalator Conversations
题意:dddd
思路:暴力枚举
diamond:
#include<bits/stdc++.h>
using namespace std;
#define int long long
void solve(){
int n,m,k,h;
cin>>n>>m>>k>>h;
int ans=0;
for (int i = 0; i < n; ++i) {
int x;
cin>>x;
int g=abs(x-h);
if(g%k==0){
// cout<<g<<endl;
if(g/k<m&&g/k>0){
ans++;
}
}
}
cout<<ans<<endl;
}
signed main(){
int t;
cin>>t;
while (t--){
solve();
}
}
B. Parity Sort
题意:给定一个无序序列,奇偶性相同的数字才能交换位置,问能否把他变为有序的
思路:菜鸡思路:记录这个数字的排完序后的位置,然后映射一下,如果他本身的位置和他最终的位置不同,就是no。大佬思路:直接排序,看当前数字与原本数字奇偶性是否相同,直接判断,tqltql
diamond:
#include<bits/stdc++.h>
using namespace std;
#define int long long
bool cmp1(pair<int,int>x,pair<int,int>y){
if(x.first!=y.first)
return x.first<y.first;
return x.second<y.second;
}
bool cmp2(pair<int,int>x,pair<int,int>y){
return x.second<y.second;
}
void solve(){
int n;
cin>>n;
vector<pair<int,int>>g(n+1);
vector<int>a(n+1);
for (int i = 1; i <=n ; ++i) {
cin>>g[i].first;
a[i]=g[i].first;
g[i].second=i;
}
sort(g.begin(),g.end(),cmp1);
for (int i = 1; i <=n ; ++i) {
g[i].first=i;
}
sort(g.begin(),g.end(),cmp2);
int vis=1;
for (int i = 1; i <=n ; ++i) {
if(a[i]%2!=a[g[i].first]%2){
vis=0;
}
}
if(vis){
cout<<"YES\n";
}
else{
cout<<"NO\n";
}
}
signed main(){
int t;
cin>>t;
while (t--){
solve();
}
}
C. Tiles Comeback
题意:balabalabalabala,其实就是要求与起点相同的数字是否有k个,与终点相同的数字是否有k个,且前者的最后一个的位置$≤$ 后者的第一个位置。
思路:就是题意
diamond:
#include<bits/stdc++.h>
using namespace std;
#define int long long
void solve(){
int n,k;
cin>>n>>k;
vector<int>q(n+1);
for (int i = 1; i <=n ; ++i) {
cin>>q[i];
}
if(q[1]==q[n]){
int ans=0;
for (int i = 1; i <=n ; ++i) {
if(q[i]==q[1]){
ans++;
}
}
if(ans>=k){
cout<<"YES\n";
return;
}
else{
cout<<"NO\n";
return;
}
}
int cnt1=0,dq=n+1;
for (int i = 1; i <=n ; ++i) {
if(q[i]==q[1]){
cnt1++;
}
if(cnt1==k){
dq=i;
break;
}
}
int cnt2=0;
for (int i = n; i >=1 ; --i) {
if(q[i]==q[n]){
cnt2++;
}
if(cnt2==k){
if(i>=dq){
cout<<"YES\n";
return;
}
else{
cout<<"NO\n";
return;
}
}
}
cout<<"NO\n";
}
signed main(){
int t;
cin>>t;
while (t--){
solve();
}
}
D. Prefix Permutation Sums
题意:给一个少了一个位置的前缀和数组,问原序列有没有可能是1到n的序列
思路:求一下后一个减前一个。分为三种情况
- 第一种是没有1的情况,少的那个前缀和是头部,如果少的那两个数字和为q[1],那么即可以
- 第二种情况是尾部为答案,首位是原序列中的数字,那么我们就少了一个数字,我们check一下,如果少了一个数字,那么就是yes
-
第三种情况是缺少了中间的一个前缀点,两数加起来是大于n的,check一下少的那两个数的和是否是最大的那个值
diamond:
#include<bits/stdc++.h> using namespace std; #define int long long void solve(){ int n; cin>>n; vector<int >q(n+1); map<int,int>mp; for (int i = 1; i <n ; ++i) { cin>>q[i]; if(i>1) mp[q[i]-q[i-1]]++; } int vis=1; for (auto i:mp) { if(i.second>1){ vis=0; break; } } if(vis){ ///没1的缺一的情况 int cnt=0; int sum=0; for (int i = 1; i <=n ; ++i) { if(mp[i]==0){ cnt++; sum+=i; } } if(cnt==2&&sum==q[1]){ cout<<"YES\n"; return; } } //首位为原序列的情况,尾部为答案,少了一个尾部 map<int,int>mp2; for (int i = 1; i <n ; ++i) { mp2[q[i]-q[i-1]]++; } int vis2=1; for (auto i:mp2) { if(i.second>1){ vis2=0; break; } } if(vis2){ int cnt=0; for (int i = 1; i <=n ; ++i) { if(mp2[i]==0){ cnt++; } } if(cnt==1){ cout<<"YES\n"; return; } } ////缺了两个中间的大于n的答案 map<int,int>mp3; int ma=-1; for (int i = 1; i <n ; ++i) { if(mp3[q[i]-q[i-1]]>0||q[i]-q[i-1]>n){ ma=q[i]-q[i-1]; } mp3[q[i]-q[i-1]]=1; } // cout<<q[1]<<' '<<q[0]; // cout<<ma<<' '; int ans=0; int cnt3=0; for (int i = 1; i <=n ; ++i) { // cout<<mp[i]<<' '; if(!mp3[i]){ ans+=i; cnt3++; } } // cout<<ans<<' '; if(ans==ma&&cnt3==2){ cout<<"YES\n"; return; } cout<<"NO\n"; } signed main(){ ios::sync_with_stdio(false),cin.tie(0),cout.tie(0); int t; cin>>t; while (t--){ solve(); } }
E. Nastya and Potions
题意:需要制成n种药剂,每种药剂的价格给出,然后有k种药剂是免费的无限的,第i 种药品可以由某几种药品制成,问每一个药剂的最小单价是多少
思路:
-
思路1:利用dfs深搜遍历每一个可以到达的点,如果这个点没有儿子,那么说明他的ans就是原价,其他的有儿子的原价与儿子的和进行取min即可
- 思路2:用一个药品的材料来连接这个药品,然后找拓扑序,当入度为0时,我们就可以求一下ans。
diamond:
-
思路1
#include<bits/stdc++.h> using namespace std; #define int long long void solve(){ int n,m; cin>>n>>m; vector<int>a(n+1); for (int i = 1; i <=n ; ++i) { cin>>a[i]; } vector<int>q[n+1]; for (int i = 0; i <m ; ++i) { int x; cin>>x; a[x]=0; } for (int i = 1; i <=n ; ++i) { int k; cin>>k; while(k--){ int y; cin>>y; if(i!=y) q[i].push_back(y); } } vector<int>ans(n+1); vector<bool>vis(n+1); function<void (int)>dfs=[&](int u){ ans[u]=a[u]; int res=1e18; if(q[u].size()!=0)res=0; for (auto i:q[u]) { if(vis[i]){ res+=ans[i]; continue; } vis[i]=1; dfs(i); res+=ans[i]; } ans[u]=min(ans[u],res); }; for (int i = 1; i <=n ; ++i) { if(vis[i])continue; vis[i]=true; dfs(i); } for (int i = 1; i <=n ; ++i) { cout<<ans[i]<<' '; } cout<<'\n'; } signed main(){ios::sync_with_stdio(false),cin.tie(0),cout.tie(0); int t; cin>>t; while (t--){ solve(); } }
-
思路2:
#include<bits/stdc++.h> using namespace std; #define int long long void solve(){ int n,m; cin>>n>>m; vector<int>a(n+1); vector<int>d(n+1); for (int i = 1; i <=n ; ++i) { cin>>a[i]; } vector<int>q[n+1]; for (int i = 0; i <m ; ++i) { int x; cin>>x; a[x]=0; } for (int i = 1; i <=n ; ++i) { int k; cin>>k; while(k--){ int y; cin>>y; q[y].push_back(i),d[i]++; } } queue<int>st; vector<int>ans(n+1); int cnt=0; for(int i=1;i<=n;i++){ if(d[i]==0) { st.push(i), cnt++; ans[i]=a[i]; } } while(st.size()){ auto t=st.front(); st.pop(); ans[t]=min(a[t],ans[t]); for(int i=0;i<q[t].size();i++){ auto g=q[t][i]; d[g]--; ans[g]+=ans[t]; if(d[g]==0){ st.push(g); } } } for (int i = 1; i <=n ; ++i) { cout<<ans[i]<<' '; } cout<<endl; } signed main(){ ios::sync_with_stdio(false),cin.tie(0),cout.tie(0); int t; cin>>t; while (t--){ solve(); } }
F. Lisa and the Martians
题意:我们的答案$(a_i \oplus x) \& (a_j \oplus x)$可以简化成当我们x取最大,全部取1时,我们只需让$a[i]$^$a[j]$最小即可,我们可以证明当x<y<z时,x^z是>=x^y||y^z的,因此我们排序后,取异或最小&111111,或者同或最大与&0000000即可
diamond:
#include <bits/stdc++.h> using namespace std; #define int long long bool cmp(pair<int,int>x,pair<int,int>y){ if(x.first==y.first)return x.second<y.second; return x.first<y.first; } void solve(){ int n,k; cin>>n>>k; vector<pair<int,int> >q(n+1); // map<int,int>mp; for(int i=1;i<=n;i++) { cin >> q[i].first; q[i].second = i; } sort(q.begin()+1,q.end()); // cout<<endl; int ma=(1ll<<k)-1; // cout<<ma<<endl; int l,r; int res=INT_MAX,ans; for (int i = 2; i <=n ; ++i) { if(res>(q[i].first^q[i-1].first)){ res=(q[i].first^q[i-1].first); l=q[i].second,r=q[i-1].second; ans = ma ^ ( q[i].first | q[i-1].first); } } cout<<l<<' '<<r<<' '<<ans<<endl; } signed main(){ ios::sync_with_stdio(false),cin.tie(0),cout.tie(0); int t; cin>>t; while (t--){ solve(); } }
G. Vlad and the Mountains
题意:n个山,高度是h[i],爬山消耗能量b-a,下山恢复能量b-a,q次询问,问初始能量为c时,能否从a山到达b山
思路:从1-2-3-4-5,能否从1到5,其实是问能否从1到其中的最高的一座山。从a到可以到b,则h[a]+e>=h_max;我们可以把边按照边权从小到大排序,然后我们开始进行合并,我们将边进行合并,把所有小于等于h[a]+e的边进行合并,那么这次询问我们就可以得到答案,因为边的合并次数就只是m次,当我们合并h[a]+e较小的那些时,我们合并的边,当遍历到更大的询问时,我们就不用合并之前的了,因为较小的能够到达的我们已经记录过了,所以如果按询问的h[a]+e从小到达排,那我们合并的次数就不会重复,连通性我们用并查集来维护,所以我们将询问的顺序也排序,记录idx即可,x1<x2<x3,当我们处理x2时,x2包括x1,那么我们就只需要处理$!(x2∩x1)$这个集合的边,处理x3时,也是只需要处理x3中$ !(x2∩x3)$,这样就可以做到一个$O(M)$的复杂度,如果这俩点在一个集合中,那么就是YES
diamond:
#pragma GCC optimize(1) #pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize("Ofast") #pragma GCC optimize("inline") #pragma GCC optimize("-fgcse") #pragma GCC optimize("-fgcse-lm") #pragma GCC optimize("-fipa-sra") #pragma GCC optimize("-ftree-pre") #pragma GCC optimize("-ftree-vrp") #pragma GCC optimize("-fpeephole2") #pragma GCC optimize("-ffast-math") #pragma GCC optimize("-fsched-spec") #pragma GCC optimize("unroll-loops") #pragma GCC optimize("-falign-jumps") #pragma GCC optimize("-falign-loops") #pragma GCC optimize("-falign-labels") #pragma GCC optimize("-fdevirtualize") #pragma GCC optimize("-fcaller-saves") #pragma GCC optimize("-fcrossjumping") #pragma GCC optimize("-fthread-jumps") #pragma GCC optimize("-funroll-loops") #pragma GCC optimize("-freorder-blocks") #pragma GCC optimize("-fschedule-insns") #pragma GCC optimize("inline-functions") #pragma GCC optimize("-ftree-tail-merge") #pragma GCC optimize("-fschedule-insns2") #pragma GCC optimize("-fstrict-aliasing") #pragma GCC optimize("-falign-functions") #pragma GCC optimize("-fcse-follow-jumps") #pragma GCC optimize("-fsched-interblock") #pragma GCC optimize("-fpartial-inlining") #pragma GCC optimize("no-stack-protector") #pragma GCC optimize("-freorder-functions") #pragma GCC optimize("-findirect-inlining") #pragma GCC optimize("-fhoist-adjacent-loads") #pragma GCC optimize("-frerun-cse-after-loop") #pragma GCC optimize("inline-small-functions") #pragma GCC optimize("-finline-small-functions") #pragma GCC optimize("-ftree-switch-conversion") #pragma GCC optimize("-foptimize-sibling-calls") #pragma GCC optimize("-fexpensive-optimizations") #pragma GCC optimize("inline-functions-called-once") #pragma GCC optimize("-fdelete-null-pointer-checks") #include<bits/stdc++.h> using namespace std; #define int long long const int N=2e5+10; int h[N],fa[N]; struct node{ int a,b,w; }; struct query{ int a,b,h_max,idx; }; bool cmp1(node x,node y){ return x.w<y.w; } bool cmp2(query x, query y){ return x.h_max<y.h_max; } int find (int x){ if(x!=fa[x]){ fa[x]=find(fa[x]); } return fa[x]; } void solve(){ vector<node>edge; vector<query>Q; int n,m; cin>>n>>m; for (int i = 1; i <=n ; ++i) { cin>>h[i]; } for (int i = 0; i <m ; ++i) { int a,b; cin>>a>>b; edge.push_back({a,b,max(h[a],h[b])}); } int q; cin>>q; sort(edge.begin(),edge.end(),cmp1); vector<bool>ans(q); for (int i = 0; i <=n ; ++i) { fa[i]=i; } for (int i = 0; i <q ; ++i) { int a,b,e; cin>>a>>b>>e; Q.push_back({a,b,h[a]+e,i}); } sort(Q.begin(),Q.end(),cmp2); int cnt=0; for (int i = 0; i <q ; ++i) { while (cnt<m&&Q[i].h_max>=edge[cnt].w){ int pa=find(edge[cnt].a),pb=find(edge[cnt].b); if(pa!=pb){ fa[pa]=pb; } cnt++; } if(find(Q[i].a)==find(Q[i].b)){ ans[Q[i].idx]=true; } else{ ans[Q[i].idx]=false; } } for (int i = 0; i <q ; ++i) { if(ans[i]){ cout<<"YES\n"; } else{ cout<<"NO\n"; } } cout<<'\n'; } signed main() {ios::sync_with_stdio(false),cin.tie(0),cout.tie(0); int t; cin>>t; while (t--)solve();
}