(Training 16)Codeforces Round #687
阿新 • • 發佈:2021-01-22
技術標籤:codeforces訓練資料結構演算法動態規劃字串
A. Prison Break
題意:給出地圖大小n*m 和點 (x,y)問地圖上距離該點最遠的點是多少
思路:4個角落必然最遠 取最大即可
#include<iostream>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
int main(){
int T;
cin>>T;
while(T--){
int n,m,x,y;
cin>> n>>m>>x>>y;
cout<<max({x-1+y-1,m-x+n-y,n-x+y-1,x-1+m-y})<<endl;
}
}
B. Repainting Street
題意:長度為n的圖 大小為K的刷子 問最少多少次能將圖刷為一個顏色
思路:首先一共10種 地圖長度是1e5
那麼我們直接向後列舉 統計上次顏色出現的位置 和 上次 刷該顏色時顏色最後保留的位置 求出需要刷多少次即可 累加求出結果
最後再以n為結尾點統計一次答案即可
#include<iostream>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
const int N=1e3+10;
int cnt[N],pre[N],pro[N];
int a[100010];
int main(){
int T;
cin>>T;
while(T--){
int n,k;
scanf("%d%d",&n,&k);
memset(cnt,0,sizeof cnt);
memset(pre,0,sizeof pre);
memset(pro,0,sizeof pro);
for(int i=1;i<=n;i++){
int x;
scanf("%d",&x);
a[i]=x;
if(pre[x]<i-1&&pro[x]<i-1){//上次塗色位置大於K
int t=(i-1-max(pre[x],pro[x])+k-1)/k;//求出需要刷多少次
cnt[x]+=t;
pro[x]=max(pro[x],pre[x])+k*t;
}
pre[x]=i;
}
int ans=0x3f3f3f3f;
for(int i=1;i<=100;i++){
if(pre[i]<n&&pro[i]<n)
cnt[i]+=(n-max(pre[i],pro[i])+k-1)/k;
ans=min(ans,cnt[i]);
}
cout<<ans<<endl;
}
}
C. Bouncing Ball
題意:刪除第一個點的時間為y 將一個點變為1的時間為x
求出使得平臺的第p個點和分別 第p+k p+2k…個點都能滿足這幾個位置為1
思路:因為只能刪除前面 所以我們考慮從後往前統計
h[i]=h[i+k]+1
和 sum[i]=sum[i+k]+(str[i]=='1')
即位置i為p的話 需要多少個1和位置i有多少個1
這時候我們就知道了 再從前往後推一次 取min
#include<iostream>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
const int N=2e5+10;
char str[N];
int sum[N],h[N];
int main(){
int T;
cin>>T;
while(T--){
int n,k,p;
memset(sum,0,sizeof sum);
memset(h,0,sizeof h);
scanf("%d%d%d",&n,&p,&k);
scanf("%s",str+1);
int x,y;
scanf("%d%d",&x,&y);
//cout<<x<<" "<<y<<endl;
int ans=1e9+10;
for(int i=n;i>=1;i--){
h[i]+=h[i+k]+1;
sum[i]+=sum[i+k]+(str[i]=='1');
}
for(int i=1;i<=n;i++){
if(i>=p){
ans=min(ans,y*(i-p)+(h[i]-sum[i])*x);
//cout<<y*(i-p)<<" "<<i-p<<" "<<(h[i]-sum[i])<<" "<<y<<endl;
}
}
cout<<ans<<endl;
}
}
D. XOR-gun
題意:給出一個升序(ai<=aj,i<j)的陣列
可以選擇2個數將他進行異或運算後加入陣列中
可以不斷進行該操作 最少多少次操作能使得陣列不滿足升序
思路:這個並不是個數據結構(字典樹)
而需要觀察 由於是異或操作 我們考慮二進位制
因為每個數均小於1e9
轉換為2進位制後 最高的數有30位
如果相鄰2個數進行異或操作後 他小於左邊的數 那麼他們這2個數必定高位相同這樣異或操作後高位被消去 那麼當如果相鄰有3個數的最高位相同 那麼必然運算元為1 而當超過60個數以後 就必定有相鄰有3個數的最高位相同 而這時候 我們只需要考慮小於60的情況 那麼我們只要進行列舉即可 不管是3次方 4次方也好。。。都能過
#include<iostream>
#include<cstring>
#include<vector>
#include<map>
#include<algorithm>
using namespace std;
const int N=1e5+10;
int a[N];
int main(){
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
a[i]^=a[i-1];
}
if(n>=60){
return puts("1"),0;
}
int ans=n;
for(int i=1;i<=n;i++){
for(int j=1;j<=i;j++)
for(int k=i+1;k<=n;k++){
if((a[i]^a[j-1])>(a[i]^a[k]))//(i+1到K k-i-2次)(i-j+1次)
ans=min(ans,k-j-1);
}
}
if(ans!=n)
cout<<ans;
else puts("-1");
return 0;
}