Codeforces Round #310 (Div. 1) A B C
3435 ワード
A Case of Matryoshkas
n個の套娃、何組かセットして、毎秒1回の操作を行うことができて、簡単に言えばセットは単一をセットすることしかできなくて、任意に分割して、すべてのセットに一緒に何秒かかるかを聞きます.水の問題は、意味の穴です.
B Case of Fugitive
n個の交差しない区間、m個の既知の長さの橋.2つの隣接区間ごとに1つの橋にまたがることが要求される.任意の解を出力し、0を出力しません.
欲張る.各グループの隣接する区間は、必要な橋の上下境界が既知であり、上界昇順に並べられ、最も短い橋を順番に二分して渡せばよい.
C Case of Chocolate
n*nのメッシュ状のチョコレートを1枚、下三角を食べて、上三角(x+y<=n+1)しか残っていません.q回の操作があり、斜線(x+y=n+1)の1つの格子を指定するたびに、上または左に食べ始め、食べられないまで食べます.毎回質問に答えるたびに何個のチェックを食べましたか.
最初は問題を見ていなかったので、二次元線分樹の神問題かと思ったら、食べ始めた点が斜線にあることに気づきました...問題を解く鍵は情報を巧みに維持することだ.毎回食べる格子のx座標を1つのsetに保存して、毎回尋ねることに対して、上へ食べるならば、xが大きいのはいつで、y座標の差を計算します;さもないとxが小さいのはいつで、x座標の差を計算します.そしてyやxを維持しなければならないので、とても巧みです.の
n個の套娃、何組かセットして、毎秒1回の操作を行うことができて、簡単に言えばセットは単一をセットすることしかできなくて、任意に分割して、すべてのセットに一緒に何秒かかるかを聞きます.水の問題は、意味の穴です.
#include <bits/stdc++.h>
using namespace std;
#define ll long long
int m[100010];
int cnt[100010];
int main(){
int n,k;
cin>>n>>k;
int ans=0;
int MAX=0;
for(int i=1;i<=k;i++){
scanf("%d",&m[i]);
int pre=0;
int num;
for(int j=1;j<=m[i];j++){
scanf("%d",&num);
if(num==pre+1){
cnt[i]++;
pre=num;
}
MAX=max(MAX,cnt[i]);
}
ans+=m[i]*2;
ans--;
}
ans-=MAX;
ans-=(MAX-1);
cout<<ans<<endl;
return 0;
}
B Case of Fugitive
n個の交差しない区間、m個の既知の長さの橋.2つの隣接区間ごとに1つの橋にまたがることが要求される.任意の解を出力し、0を出力しません.
欲張る.各グループの隣接する区間は、必要な橋の上下境界が既知であり、上界昇順に並べられ、最も短い橋を順番に二分して渡せばよい.
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=200010;
ll l[maxn];
ll r[maxn];
ll a[maxn];
int n,m;
int ans[maxn];
struct node{
ll MIN;
ll MAX;
int id;
bool operator<(const node other)const{
return MAX<other.MAX;
}
}seg[maxn];
struct Bridge{
ll len;
int id;
bool operator<(const Bridge other)const{
if(len!=other.len)return len<other.len;
return id<other.id;
}
};
int main(){
cin>>n>>m;
for(int i=0;i<n;i++){
scanf("%I64d%I64d",&l[i],&r[i]);
}
for(int i=0;i<n-1;i++){
seg[i].MIN=l[i+1]-r[i];
seg[i].MAX=r[i+1]-l[i];
seg[i].id=i;
}
set<Bridge> Set;
Bridge bb;
for(int i=0;i<m;i++){
scanf("%I64d",&bb.len);
bb.id=i;
Set.insert(bb);
}
sort(seg,seg+n-1);
bool ok=1;
for(int i=0;i<n-1;i++){
Bridge tmp; tmp.len=seg[i].MIN;
tmp.id=-1;
set<Bridge>::iterator it=Set.lower_bound(tmp);
if((*it).len>seg[i].MAX){
ok=0;
break;
}else{
ans[seg[i].id]=it->id;
Set.erase(*it);
}
}
if(ok){
cout<<"Yes"<<endl;
for(int i=0;i<n-1;i++){
printf("%d ",ans[i]+1);
}
}else{
cout<<"No"<<endl;
}
return 0;
}
C Case of Chocolate
n*nのメッシュ状のチョコレートを1枚、下三角を食べて、上三角(x+y<=n+1)しか残っていません.q回の操作があり、斜線(x+y=n+1)の1つの格子を指定するたびに、上または左に食べ始め、食べられないまで食べます.毎回質問に答えるたびに何個のチェックを食べましたか.
最初は問題を見ていなかったので、二次元線分樹の神問題かと思ったら、食べ始めた点が斜線にあることに気づきました...問題を解く鍵は情報を巧みに維持することだ.毎回食べる格子のx座標を1つのsetに保存して、毎回尋ねることに対して、上へ食べるならば、xが大きいのはいつで、y座標の差を計算します;さもないとxが小さいのはいつで、x座標の差を計算します.そしてyやxを維持しなければならないので、とても巧みです.の
#include <bits/stdc++.h>
using namespace std;
#define mp make_pair
#define pii pair<int,int>
const int maxn=200010;
int x[maxn];
int y[maxn];
int main(){
int n,q;
char dir[2];
cin>>n>>q;
set<pii> s; set<pii>::iterator it;
s.insert(mp(0,q+1)); x[q+1]=0; y[q+1]=n+1;
s.insert(mp(n+1,q+2)); x[q+2]=n+1; y[q+2]=0;
for(int i=1;i<=q;i++){
scanf("%d%d%s",&x[i],&y[i],dir);
if(dir[0]=='L'){ //
it = s.upper_bound(mp(x[i]+1,0));
it--;
}else{ //
it = s.lower_bound(mp(x[i],0));
}
if(it->first==x[i]){
printf("0
");
continue;
}
s.insert(mp(x[i],i));
if(dir[0]=='L'){
printf("%d
",x[i]-x[it->second]);
x[i]=x[it->second];
}else{
printf("%d
",y[i]-y[it->second]);
y[i]=y[it->second];
}
}
return 0;
}