AIM Tech Round 5 1028cf(A-E)
阿新 • • 發佈:2018-08-30
很多 pre arr 註意 -m ref 可能 accept scan
AIM Tech Round 5 (codeforces上題目編號是1028)(A-E)
---完全被這次比賽打擊,自己真的很渣---
戰況
- 依舊3題選手
- 被構造題坑得好慘
- 稍稍漲了rating,希望下次比賽好好準備進入藍名,就可以被div1虐了
題目看題解也很難懂呀
A. Find Square
水題,找出矩形得中心,可以略過
B. Unnatural Conditions
題意:
- s(A)代表數字A各個數位之和即s(1234)=1+2+3+4=10
- 給出 m,n,需要求出滿足條件A,B;s(A)>=m,s(B)>=m,s(A+B)<=n
- 自己也是想了一會才知道是構造題目(畢竟沒經驗),但我一直蜜汁自信構造這s(A)=m,s(B)=m但min(s(A+B))的情況
- 實際上s(A),s(B)的大小和s(A+B)完全沒有相關性,s(A),s(B)都可以無限大,s(A+B)最小可以是1
- so 就是這樣呀:
- A=55555555555555555555555555555555555
- B=44444444444444444444444444444444445
這樣一想已變成水題(連讀入都不需要讀了),代碼略
C. Rectangles
題意
- 給k個矩形,找出任意(k-1)個矩形相交區域的點(即相交區域任一點即可)
- 程序的判定大概是這樣應該是算出所有(k-1)個相較矩形的並,然後判定我們輸出的點是否在這些區域內
- 我的做法不同於標程,我是按照之前比賽的求線段(k-1)交的題目方法做的
- 將其看作兩維情況,同時抽掉一個矩形,觀察影響x軸線段並和y軸線段並,如果還有區間,輸出即可
- 我的程序時間復雜度是O(nlogn)(需要排序),但其實可以優化因為只需有的最小值,次小值,最大值和次大值,這樣就是O(n)
- 標答的做法是采用前綴最大預處理前綴最大並區域和後綴最大並區域(真的是很聰明的方法)
這裏只給出我的做法
代碼
#include<bits/stdc++.h> using namespace std; const int maxn=140000; int xl[maxn]; int xr[maxn],yd[maxn],yu[maxn]; int tmpx1[maxn],tmpx2[maxn],tmpy1[maxn],tmpy2[maxn]; bool help(int x,int y,int x1,int x2,int y1,int y2){ return (x>=x1&&x<=x2)&&(y>=y1&&y<=y2); } int main(){ int x1,y1,x2,y3; int n; cin>>n; for(int i=1;i<=n;i++){ scanf("%d %d %d %d",&xl[i],&yd[i],&xr[i],&yu[i]); tmpx1[i]=xl[i];tmpx2[i]=xr[i];tmpy1[i]=yd[i];tmpy2[i]=yu[i]; } //printf("db raed over\n"); sort(xl+1,xl+1+n); sort(xr+1,xr+1+n); int tl=xl[n],tr=xr[1]; sort(yd+1,yd+1+n); sort(yu+1,yu+1+n); int td=yd[n],tu=yu[1]; for(int i=1;i<=n;i++){ int tl=xl[n],tr=xr[1]; int td=yd[n],tu=yu[1]; //printf("db1:%d %d %d %d %d\n",i,tl,tr,td,tu); if(tmpx1[i]==xl[n]) tl=xl[n-1]; if(tmpx2[i]==xr[1]) tr=xr[2]; if(tmpy1[i]==yd[n]) td=yd[n-1]; if(tmpy2[i]==yu[1]) tu=yu[2]; //printf("db2:%d %d %d %d %d\n",i,tl,tr,td,tu); if(tr>=tl&&tu>=td){ //printf("db:%d %d %d %d %d\n",i,tl,tr,td,tu); printf("%d %d\n",tl,td); return 0; } } return 0; }
D. Order book
題意
- 個人感覺題目真的很毒瘤,題意很長而且難懂,所以比賽時果斷放棄
- 一個本本裏記錄著 sell mi;buy ni 這樣兩種形式的內容;每次達成一次交易是min(mi) max(ni),然後刪除這樣兩項
- 現在給出add m;accept n;表示加入某項(並不知是sell or buy),accept n 代表一次交易(可能是buy n也可能是sell n)
- 現在求有多少可能情況(很毒瘤吧)
- 可以分析每次accept就能確定很多情況,所以維護min(sell)和max(buy)
- 如果在max(buy)-min(sell)區間內則情況數翻倍,並且更新min(sell) max(buy) 刪除accept的元素
最終剩下的Min(sell) max(buy)的區間長度就是情況數另一個因子(可以枚舉sell的位置,比sell大的都是sell)
代碼如下
#include<bits/stdc++.h>
using namespace std;
#define ll long long
int n;
ll modv=1e9+7;
ll p;
char str[10];
set<ll> s;
ll lo=-1e9,hi=1e9;
ll ans=1;
int main(){
scanf("%lld",&n);
s.insert(lo);s.insert(hi);
for(ll i=1;i<=n;i++){
scanf("%s %lld",str,&p);
if(str[1]=='D'){
s.insert(p);
}
else{
if(p<lo||p>hi){printf("0\n");return 0;}
if(p>lo&&p<hi){
ans=(ans*2)%modv;
}
auto it=s.find(p);
lo=*prev(it);
hi=*next(it);
s.erase(it);
}
}
int res=0;
for(auto it=s.find(lo);it!=s.find(hi);it++){
res++;
}
printf("%lld\n",(res*ans)%modv);
return 0;
}
E. Restore Array(毒瘤構造題,不過很多人都構造出來了,是我太渣,還是自己見識太少)
題意
- 數組 a[n]是由b[n] 通過a[i]=b[i]%bi+1得到的
- 試根據a[n]求得b[n]
- 構造題,沒有唯一解,需判定解的存在性;大概思想是根據差項得到a[i],所以b[i]是某種形式的前綴和或者後綴和(註意足夠大)
作為基準(起點)的應該是a[i]==max&&a[i]>a[i-1]
代碼
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll N=200005;
ll a[N];
ll b[N];
int mod(int a,int p){
if(a%p==0) return p;
else return a%p;
}
int main(){
ll n;
cin>>n;
ll minv=INT_MAX,maxv=INT_MIN;
for(ll i=1;i<=n;i++){
scanf("%d",a+i);
minv=min(a[i],minv);
maxv=max(a[i],maxv);
}
if(minv==maxv){
//maybe No
if(minv==0){
//construct same
printf("Yes\n");
for(int i=1;i<=n;i++){
printf("%lld ",(ll)1);
}
}
else{
printf("No\n");
}
}
else{
int maxindex=-1;
a[0]=a[n];
for(ll i=1;i<=n;i++){
if(a[i]==maxv&&a[i-1]<maxv){maxindex=i;break;}
}
b[maxindex]=a[maxindex];
//int lo=(maxindex-1+n)%n;
int lo=mod(maxindex-1+n,n);
b[lo]=a[lo]+maxv*2;
//cout<<lo<<b[lo]<<endl;
for(int i=n-2;i>=1;i--){
//b[(i+maxindex)%n]=b[(i+1+maxindex)%n]+a[(i+maxindex)%n];
b[mod(i+maxindex,n)]=b[mod(i+1+maxindex,n)]+a[mod(i+maxindex,n)];
}
printf("Yes\n");
for(int i=1;i<=n;i++){
printf("%lld ",b[i]);
}
}
return 0;
}
求下一次藍名啊,我要打div1!!!!
AIM Tech Round 5 1028cf(A-E)