A. Sonya and Hotels
这题没啥说的,就是int爆了要用long long
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int ans;
ll n,a[102],d;
int main(){
ll i,j,q;
scanf("%I64d%I64d",&n,&d);
for(i=1;i<=n;++i)scanf("%I64d",&a[i]);
sort(a+1,a+n+1);
ans=2;
for(i=1;i<n;++i){
j=a[i]+d;
if(a[i+1]>=j+d) ans++;
q=a[i+1]-d;
if(q>a[i]+d) ans++;
}
printf("%d",ans);
}
B. Sonya and Exhibition
看题一脸懵逼??这是个B???
切完C才反应过来:
不管怎样增加区间要求,我们只要01间隔轮流摆总是没错的…
跪在b题,还是我太菜
#include<bits/stdc++.h>
using namespace std;
int n,m,x,y,i;
int main(){
scanf("%d%d",&n,&m);
for(i=1;i<=m;++i) scanf("%d%d",&x,&y);
for(i=1;i<=n;++i) printf("%c",'0'+(i&1));
}
C. Sonya and Robots
离散化一下,标记一下每个值第一次和最后一次出现的位置,指针扫一遍即可。
同样注意用long long
include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
typedef long long ll;
int n,v[N],z[N],f[N],a[N],b[N],cnt;
ll ans;
inline bool cmp(const int &x,const int &y){return z[v[x]]<z[v[y]];}
inline bool cmq(const int &x,const int &y){return f[v[x]]<f[v[y]];}
int main(){
int i,j;
scanf("%d",&n);
for(i=1;i<=n;++i){
scanf("%d",&a[i]);
if(!z[a[i]]) z[a[i]]=i;
f[a[i]]=i;
}
sort(a+1,a+n+1);v[++cnt]=a[1];
for(i=2;i<=n;++i){
if(a[i]!=a[i-1]){
v[++cnt]=a[i];
}
}
for(i=1;i<=cnt;++i) a[i]=b[i]=i;
sort(a+1,a+cnt+1,cmp);sort(b+1,b+cnt+1,cmq);
for(j=1,i=1;i<=cnt;++i){
while(f[v[b[j]]]<=z[v[a[i]]] && j<=cnt)
++j;
ans+=(cnt-j+1);
}
printf("%I64d",ans);
}
D. Sonya and Matrix
这题挺有意思的.
感觉把图旋转一下也没有什么区别。所以随便找一个x最小的答案就好啦。
可以发现,找到值最小的数
i(i>0)
i
(
i
>
0
)
且i的出现次数小于4*i次,这个i就等于0的x坐标。
同样假设可以把整个矩形分成左上左下右上右下四块,强行让0在右下这块,那么离它最远的必然是左上角的点,也就是数组里的最大值,设为
b=m+n−x−y
b
=
m
+
n
−
x
−
y
。
设
(x,y)
(
x
,
y
)
离右下角的距离
a=x+y−2
a
=
x
+
y
−
2
然后就枚举t的因数即枚举n,m的值,此时知道了
n,m,b,x
n
,
m
,
b
,
x
,
y
y
由上面等式自然就推出来了,于是暴力算一遍这个数组,和原数组比较。
这个复杂度…
n−−√
n
的枚举还套上
nlogn
n
log
n
的排序和有常数的枚举。
总之cf评测机能过
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
int t,q[N],b,a,m,n,x,y,res[N],cnt;
inline void check()
{
if((a>b) || (a<0) || (y<0)) return;\
if((!(n&1) && n<x*2) || ((n&1) && n+1<x*2)) return;
if((!(m&1) && m<y*2) || ((m&1) && m+1<x*2)) return;
int i,j;cnt=0;
for(i=1;i<=n;++i)
for(j=1;j<=m;++j)
{res[++cnt]=abs(i-x)+abs(j-y);}
sort(res+1,res+t+1);
for(i=1;i<=t;++i) if(res[i]!=q[i]) return;
printf("%d %d\n%d %d",n,m,x,y);exit(0);
}
int main(){
int i,j;
scanf("%d",&t);
for(i=1;i<=t;++i) scanf("%d",&q[i]);
if(t==1){
if(q[1]==0) printf("1 1\n1 1\n");
else printf("-1\n");
return 0;
}
sort(q+1,q+t+1);
for(i=2;i<=t;i=j+1){
for(j=i;q[j+1]==q[i] && j<t;++j);
if((j-i+1)!=4*q[i]){x=q[i];break;}
}
b=q[t];
for(i=1;i*i<=t;++i) if(t%i==0){
n=i;m=t/i;y=m+n-b-x;
a=m+n-b-2;check();
if(i*i!=t){swap(m,n);check();}
}
printf("-1\n");
}
E. Sonya and Ice Cream
这题的贪心也很有意思。
可以肯定这样一条长度不超过k-1的链必然是直径上的一段子序列。
不详说,很好证明。
那么就先找出最长链建两个指针分别指向链的两个端点,不断向内跳直到长度不超过k-1。而且可以肯定,当长度不超过k-1时,
len=min(diameter,k−1)
l
e
n
=
m
i
n
(
d
i
a
m
e
t
e
r
,
k
−
1
)
一定能使答案最优。
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int mx[N],f[N],dis[N];
int n,k,rt,dt,hd,tl,d[N],in[N];
int head[N],to[N<<1],nxt[N<<1],w[N<<1],tot;
int son[N];
inline void lk(int u,int v,int c)
{to[++tot]=v;nxt[tot]=head[u];head[u]=tot;w[tot]=c;}
inline void dfs(int x)
{
int i,j,mx1=x,mx2=x;mx[x]=x;
for(i=head[x];i;i=nxt[i]){
j=to[i];if(j==f[x]) continue;
f[j]=x;d[j]=d[x]+1;dis[j]=dis[x]+w[i];dfs(j);
if(dis[mx[j]]>dis[mx1]){
mx2=mx1;mx1=mx[j];
}else if(dis[mx[j]]>dis[mx2]){
mx2=mx[j];
}
}
mx[x]=mx1;if(dis[mx1]+dis[mx2]-2*dis[x]>dt){
dt=dis[mx1]+dis[mx2]-2*dis[x];
hd=mx1;tl=mx2;rt=x;
}
}
inline void df(int x)
{
int i,j;
for(i=head[x];i;i=nxt[i]){
j=to[i];if(j==f[x]) continue;
if(in[x] && in[j]) son[x]=j;
f[j]=x;d[j]=d[x]+1;dis[j]=dis[x]+w[i];
df(j);
}
}
inline void dfss(int x)
{
int i,j;mx[x]= in[x]? 0:x;
for(i=head[x];i;i=nxt[i]){
j=to[i];if(j==f[x]) continue;
dis[j]=dis[x]+w[i];f[j]=x;dfss(j);
if(dis[mx[j]]>dis[mx[x]]) mx[x]=mx[j];
}
if(in[x]) {dt=max(dt,dis[mx[x]]-dis[x]);mx[x]=0;}
}
int main(){
int i,j,ix,iy,iz,upl,upr,l=0,r=0,sonl,sonr;
scanf("%d%d",&n,&k);
for(i=1;i<n;++i){
scanf("%d%d%d",&ix,&iy,&iz);
lk(ix,iy,iz);lk(iy,ix,iz);
}
dfs(1);
for(i=hd;i!=rt && f[i]!=rt;i=f[i]) in[i]=1;
if(f[i]==rt) sonl=i,in[i]=1;
for(i=tl;i!=rt && f[i]!=rt;i=f[i]) in[i]=1;
if(f[i]==rt) sonr=i,in[i]=1;
in[rt]=1;
ix=d[hd]+d[tl]-2*d[rt]-k+1;
f[rt]=0;d[rt]=0,dis[rt]=0;df(rt);
upl= (d[hd]>d[rt]);upr=(d[tl]>d[rt]);
for(;ix>0;ix--){
if(upl) i=-(dis[f[hd]]-dis[hd]);
else i= hd==rt?-(dis[rt]-dis[sonr]):-(dis[hd]-dis[son[hd]]);
if(upr) j=-(dis[f[tl]]-dis[tl]);
else j= tl==rt?-(dis[rt]-dis[sonl]):-(dis[tl]-dis[son[tl]]);
if(l+i<=j+r){
l+=i;in[hd]=0;if(upl) hd=f[hd];else hd= rt==hd? sonr:son[hd];
if(hd==rt) upl=0;
}else{
r+=j;in[tl]=0;if(upr) tl=f[tl];else tl= rt==tl? sonl:son[tl];
if(tl==rt) upr=0;
}
}
dt=0;dis[hd]=0;f[hd]=0;dfss(hd);
printf("%d\n",dt);
}
F. Sonya and Bitwise OR
先留个坑。
本文详细解析了Codeforces Round 495 Div. 2比赛中的六道题目,从简单的酒店选择问题到复杂的矩阵操作及图论问题,覆盖了数据结构、算法优化等多个方面。
1343

被折叠的 条评论
为什么被折叠?



