A.Alice 和 Bob
題意:
給定序列A和序列,m組資訊\((i,j)\),Alice可以交換\(A_i\)和\(A_j\)任意次,判斷Alice是否能將序列A轉變為序列B。
思路
由於Alice可以任意調整m組資訊,所以題目所給m組資訊\((i,j)\)不影響結果。先考慮k組資訊,第i組為\((T_i,T_{i+1})\),\(1\leq T_1\lt T_2\lt...\lt T_{k+1}\le n\),Alice可以任意次使用這k組資訊,所以Alice可以任意排序\(A_{T_1},A_{T_2},...,A_{T_{k+1}}\)這k+1個數。所以可以根據B的排列,將A與B不同的數分為若干組,每組可以透過\({k_i}\)組資訊來排序。用並查集分組即可。
程式碼
點選檢視程式碼
#include <bits/stdc++.h>
#define int long long
#define MOD 10000000000ll
#define PII pair<int,int>
#define PIII pair<int,PII>
#define endl '\n'
using namespace std;
int a[200005],b[200005],c[200005];
int fa[200005];
int find(int x) {
return x == fa[x] ? x : (fa[x] = find(fa[x]));
}
void merge(int i, int j) {
fa[find(i)] = find(j);
}
int32_t main() {
ios::sync_with_stdio(false);
cin.tie(NULL); cout.tie(NULL);
int T = 1;
cin >> T;
while (T--) {
int n,m,s=0;
cin>>n;
for(int i=1;i<=n;i++){
fa[i]=i;
cin>>a[i];
c[a[i]]=i;
}
for(int i=1;i<=n;i++){
cin>>b[i];
if(b[i]!=a[i]){
merge(i,c[b[i]]);
}
}
for(int i=1;i<=n;i++){
if(find(i)!=i){
s++;
}
}
//cout<<s<<endl;
cin>>m;
for(int i=0;i<m;i++){
int x,y;
cin>>x>>y;
}
if(s>m){
cout<<"No\n";
}else{
cout<<"Yes\n";
}
}
return 0;
}
B.Haoo的異或
題意:
求x,使得\((1\oplus x)\oplus(2\oplus x)\oplus...\oplus(n\oplus x)\)最小。
思路
由異或性質可得,n為奇數時,\((1\oplus x)\oplus(2\oplus x)\oplus...\oplus(n\oplus x)=(1\oplus2\oplus...\oplus n)\oplus x\),n為偶數時,\((1\oplus x)\oplus(2\oplus x)\oplus...\oplus(n\oplus x)=(1\oplus2\oplus...\oplus n)\),預處理\(1\oplus2\oplus...\oplus n\)即可
程式碼
點選檢視程式碼
#include <bits/stdc++.h>
#define int long long
#define MOD 10000000000ll
#define PII pair<int,int>
#define PIII pair<int,PII>
#define endl '\n'
using namespace std;
int a[200005],b[200005],c[200005];
int fa[200005];
int32_t main() {
ios::sync_with_stdio(false);
cin.tie(NULL); cout.tie(NULL);
for(int i=1;i<=1e5;i++){
a[i]=i;
a[i]^=a[i-1];
}
int T = 1;
cin >> T;
while (T--) {
int n;
cin>>n;
if(n%2){
cout<<a[n]<<endl;
}else{
cout<<"no one"<<endl;
}
}
return 0;
}
C.死亡左輪
題意:
有Q次詢問,每次詢問一個區間[l,r]表示,從第l個人開始到第r個人,玩死亡左輪,每人依次開一槍,請問第幾個人最先死亡?
思路
求從\(i\)開始遊戲第一個死的人,用一個偏移量來維護當前的彈巢位置,每次對有子彈的彈巢位置遍歷即可。對於每個\(l\),查詢從\(l\)開始遊戲第一個死的人,若小於等於\(r\),則輸出此人,否則無人死亡。
程式碼
點選檢視程式碼
#include <bits/stdc++.h>
#define int long long
#define MOD 10000000000ll
#define PII pair<int,int>
#define PIII pair<int,PII>
#define endl '\n'
using namespace std;
int mx=1000005;
int a[1000005],b[1000005],c[100005];
vector<int>d[100];
priority_queue<PII,vector<PII>,greater<PII>>qq;
string s;
vector<PII>q,p;
vector<int>ans;
int32_t main() {
ios::sync_with_stdio(false);
cin.tie(NULL); cout.tie(NULL);
int T = 1;
//cin >> T;
while (T--) {
int n,m,k,sum=0;
cin>>m>>n>>k;
for(int i=0;i<n;i++){
c[i]=-1;
}
for(int i=0;i<m;i++){
cin>>b[i];
}
int pk=0;
for(int i=0;i<n;i++){
cin>>a[i];
for(int j=0;j<m;j++){
if(b[((pk-j)%m+m)%m]){
for(int k=0;k<d[j].size();k++){
c[d[j][k]]=i;
}
d[j].clear();
}
}
d[(pk)%m].emplace_back(i);
pk+=a[i];
}
for(int i=0;i<k;i++){
int l,r;
cin>>l>>r;
l--;
if(b[0]==1){
cout<<1<<endl;
}else{
if(c[l]!=-1&&r>=c[l]+1){
cout<<c[l]+1<<endl;
}else{
cout<<"No one died"<<endl;
}
}
}
}
return 0;
}
D.構造字串
題意:
構造一個長度最短的字串,滿足 cqust 和 tsuqc 這兩個字串在字串中分別出現了x次和y次。
思路
模擬即可
程式碼
點選檢視程式碼
#include <bits/stdc++.h>
#define int long long
#define MOD 10000000000ll
#define PII pair<int,int>
#define PIII pair<int,PII>
#define endl '\n'
using namespace std;
int a[200005],b[200005],c[200005];
int fa[200005];
int32_t main() {
ios::sync_with_stdio(false);
cin.tie(NULL); cout.tie(NULL);
int T = 1;
cin >> T;
while (T--) {
int x,y;
string s,s1="cqust",s2="tsuqc",s3="cqustsuq",s4="tsuqcqus";
cin>>x>>y;
if(x>y){
for(int i=0;i<min(x,y);i++){
s+=s3;
}
for(int i=0;i<x-min(x,y);i++){
s+=s1;
}
}else if(x<y){
for(int i=0;i<min(x,y);i++){
s+=s4;
}
for(int i=0;i<y-min(x,y);i++){
s+=s2;
}
}else{
for(int i=0;i<min(x,y);i++){
s+=s3;
}
s+='c';
}
cout<<s<<endl;
}
return 0;
}
E.奇怪的排序
題意:
略。
思路
找連續的不相交的區間[l,r]滿足\(\forall i,a[i]\neq i\)的個數。
程式碼
點選檢視程式碼
#include <bits/stdc++.h>
#define int long long
#define MOD 10000000000ll
#define PII pair<int,int>
#define PIII pair<int,PII>
#define endl '\n'
using namespace std;
int a[1000005],b[200005],c[200005];
int fa[200005];
string s;
int32_t main() {
ios::sync_with_stdio(false);
cin.tie(NULL); cout.tie(NULL);
int T = 1;
cin >> T;
while (T--) {
int n,f=0,sum=0;
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
if(a[i]!=i){
f=1;
}else{
sum+=f;
f=0;
}
}
sum+=f;
cout<<sum<<endl;
}
return 0;
}
F.畫畫的 baby
思路
模擬。
程式碼
點選檢視程式碼
#include <bits/stdc++.h>
#define int long long
#define MOD 10000000000ll
#define PII pair<int,int>
#define PIII pair<int,PII>
#define endl '\n'
using namespace std;
int mx=1000005;
int a[1000005],b[1000005],c[1000005],d[1000005];
string s;
vector<PII>q,p;
vector<int>ans;
int lowbit(int x){
return x&-x;
}
int getsum1(int x) {
int ans = 0;
while (x > 0) {
ans = ans + c[x];
x = x - lowbit(x);
}
return ans;
}
void add1(int x, int k) {
while (x <= mx) {
c[x] = c[x] + k;
x = x + lowbit(x);
}
}
int32_t main() {
ios::sync_with_stdio(false);
cin.tie(NULL); cout.tie(NULL);
int T = 1;
//cin >> T;
while (T--) {
int n,sum=0;
cin>>n;
for(int i=0;i<n;i++){
int x,y,f=1;
cin>>x>>y;
q.emplace_back(PII{x,y});
if(!a[y])add1(y,1);
a[y]++;
}
sort(q.begin(),q.end());
int qx,qy,l=0;
for(int i=0;i<n;i++){
int x=q[i].first,y=q[i].second;
if(x==qx&&y==qy){
a[y]--;
if(!a[y])add1(y,-1);
continue;
}
//cout<<x<<' '<<y<<endl;
if(i){
if(x==qx){
sum+=y-qy;
sum+=x-l-1;
sum+=(getsum1(y-1)-getsum1(qy))*(x-l-1);
//cout<<"getsum1(y-1)-getsum1(qy) "<<getsum1(y-1)-getsum1(qy)<<endl;
}else{
sum+=(getsum1(1e6)-getsum1(qy))*(qx-l);
l=qx;
sum+=y;
sum+=x-l-1;
sum+=getsum1(y-1)*(x-l-1);
//cout<<"getsum1(y-1) "<<getsum1(y-1)<<endl;
}
}else{
sum+=x+y-1;
sum+=getsum1(y-1)*(x-1);
}
qx=x,qy=y;
//cout<<sum<<endl;
a[y]--;
if(!a[y])add1(y,-1);
}
cout<<sum<<endl;
}
return 0;
}
G.魔王降世
題意:
給定n個村莊的座標位置和m個火山的座標位置,有Q次詢問,每次詢問第\(t_i\)秒的時候,有多少個村莊遭到破壞?。
思路
計算每個村莊離最近的火山的距離,排序,二分查詢即可
程式碼
點選檢視程式碼
#include <bits/stdc++.h>
#define int long long
#define MOD 10000000000ll
#define PII pair<int,int>
#define PIII pair<int,PII>
#define endl '\n'
using namespace std;
int a[1000005],b[200005],c[200005];
int fa[200005];
string s;
vector<PII>q,p;
vector<int>ans;
int32_t main() {
ios::sync_with_stdio(false);
cin.tie(NULL); cout.tie(NULL);
int T = 1;
//cin >> T;
while (T--) {
int n,m,Q;
cin>>n>>m>>Q;
for(int i=0;i<n;i++){
int x,y;
cin>>x>>y;
q.emplace_back(PII{x,y});
}
for(int i=0;i<m;i++){
int x,y;
cin>>x>>y;
p.emplace_back(PII{x,y});
}
for(int j=0;j<n;j++){
int mn=INT64_MAX;
for(int i=0;i<m;i++){
mn=min(mn,(p[i].first-q[j].first)*(p[i].first-q[j].first)+(p[i].second-q[j].second)*(p[i].second-q[j].second));
}
ans.emplace_back(mn);
}
sort(ans.begin(),ans.end());
for(int i=0;i<Q;i++){
int t;
cin>>t;
int pos=upper_bound(ans.begin(),ans.end(),t*t)-ans.begin();
cout<<pos<<endl;
}
}
return 0;
}
H.波峰交叉 k 序列
思路
不會
程式碼
I.禮物商店
題意:
每次購買物品後價格會由\(x\)變為\((x+k)|(x\&k)\),最少花多少錢能買到n件商品。
思路
因為\((x+k)|(x\&k)\geq(x+k)\),貪心,每次選取價格最小的物品,最後注意購買次數即可。
程式碼
點選檢視程式碼
#include <bits/stdc++.h>
#define int long long
#define MOD 10000000000ll
#define PII pair<int,int>
#define PIII pair<int,PII>
#define endl '\n'
using namespace std;
int mx=1000005;
int a[1000005],b[1000005],c[1000005],d[1000005];
priority_queue<PII,vector<PII>,greater<PII>>qq;
string s;
vector<PII>q,p;
vector<int>ans;
int32_t main() {
ios::sync_with_stdio(false);
cin.tie(NULL); cout.tie(NULL);
int T = 1;
//cin >> T;
while (T--) {
int n,m,k,sum=0;
cin>>n>>m>>k;
for(int i=0;i<m;i++){
cin>>a[i];
}
for(int i=0;i<m;i++){
int x;
cin>>x;
qq.push(PII{x,i});
}
for(int i=0;i<n;i++){
if(a[qq.top().second]){
a[qq.top().second]--;
sum+=qq.top().first;
int t=(qq.top().first+k)|(qq.top().first&k);
int ii=qq.top().second;
qq.pop();
qq.push(PII{t,ii});
}else{
qq.pop();
i--;
}
}
cout<<sum<<endl;
}
return 0;
}
J.切割 01 串
題意:
求切割的最大次數
思路
每次切割可以刪去一個0或1,所以最大次數為n-1,判斷字串內是否有1即可。
程式碼
點選檢視程式碼
#include <bits/stdc++.h>
#define int long long
#define MOD 10000000000ll
#define PII pair<int,int>
#define PIII pair<int,PII>
#define endl '\n'
using namespace std;
int a[200005],b[200005],c[200005];
int fa[200005];
string s;
int32_t main() {
ios::sync_with_stdio(false);
cin.tie(NULL); cout.tie(NULL);
int T = 1;
cin >> T;
while (T--) {
cin>>s;
int sum=0,f=0;
for(int i=0;i<s.length();i++){
if(s[i]=='1'){
f=1;
}
}
if(f)cout<<s.length()-1<<endl;
else cout<<0<<endl;
}
return 0;
}