不是我没写题目名称,是题目名称就是:T1,T2,T3。。
T1:
题目大意:给出一个长度为(2n)实数数列,你可以把其中(n)个数向上取整,其余向下取整,求操作完后数列和与原来数列和的差的绝对值的最小值。
起初感觉毫无头绪,但在yyh的提醒下,发现也就是求全部(1-a_i-a_j)之和所以,用区间长度除以二减去所有的数就好了。(把所有数的整数部分去掉)
但写完我们就发现了问题,如果输入的数为整数,那向上取整和向下取整的值是一样的,就会造成(1-a_i-a_j)等价于(a_i-a_j),然后,我们就想到了一个很好的解决办法——换个算法。。
其实我们把整个序列分成整数和小数两个部分,分别处理,整数部分就是用来平衡小数部分上下取整的数量问题的。
然后我们可以简化问题,也就是说我们要把整个序列(小数部分)变成(0)与(1),两这个数不一定相等,因为有整数可以用来平衡,所以就可以二分一个(1)的数量,然后比较更新答案。时间复杂度为(O(nlongn))。
小结:
解题关键:想到简化题意并二分答案。
芝士点:二分答案
这题主要还是靠思维能力。
终于上代码啦:
#include<bits/stdc++.h>
#define re register
using namespace std;
const int N=500005;
int n,Q,num[N],l,r;
double aa[N],a[N],sum[N];
inline bool check(int x,int y,int m){return sum[y]-sum[x-1]-m>0;}
int main()
{
scanf("%d%d",&n,&Q);
for(re int i=1;i<=n;i++)
{
scanf("%lf",&aa[i]);
num[i]=num[i-1]+(aa[i]-floor(aa[i])>0);
sum[i]=sum[i-1]+aa[i]-floor(aa[i]);
}
for(re int i=1,x,y,ls;i<=Q;i++)
{
scanf("%d%d",&x,&y);
ls=l=max(0,num[y]-num[x-1]-(y-x+1>>1));
r=min((y-x+1)>>1,num[y]-num[x-1]);
for(re int mid=(l+r)>>1;l<r;mid=(l+r)>>1)
{
if(check(x,y,mid))l=mid+1;
else r=mid;
}
printf("%.3lf
",min(abs(sum[y]-sum[x-1]-l),l>ls?abs(sum[y]-sum[x-1]-l+1):0x3f3f3f3f));
}
return 0;
}
T2
题目大意:给出一棵树与(m)个限制,求任意一个满足此要求的点。限制具体如下:该点到(a_i)与(b_i)的距离和不超过(d_i)。如果没有满足条件的点,则输出"NO"。
首先我们可以发现,该点一定是在深度最大的限制的上方,即
[dep[a]-dep[x]+dep[b]-dep[x]le d
]
[Rightarrow dep[x]ge frac{dep[a]+dep[b]-d}{2}
]
其中(x)是我们要求的点,因为此限制深度最大,所以我们最好让(x)在满足这个限制的情况下深度最小,即求最大的(frac{dep[a]+dep[b]-d}{2})。
我们就可以在输入时处理出这个节点,然后一边DFS搜索看是否满足所有条件,如果是则输出这个节点,否则输出"NO"。时间复杂度为(O(n))。
小结:
解题关键:想到将条件转化,就极容易求解。
芝士点:DFS??
这题和上一题一样,也是主要靠思维
手起,码落:
#include<bits/stdc++.h>
#define re register
using namespace std;
inline int read()
{
re int x=0,f=1;
re char ch=getchar();
for(;ch>'9'||ch<'0';ch=getchar())if(ch=='-')f*=-1;
for(;ch>='0'&&ch<='9';ch=getchar())x=(x<<1)+(x<<3)+(ch^48);
return x*f;
}
const int N=100005;
struct egde{int v,net;}e[N<<1];
int n,m,fa[N],cnt,hd[N],dep[N],a[N],b[N],d[N],ma,mx,my,dis[N];
inline void add(int v,int u)
{
e[++cnt].v=v,e[cnt].net=hd[u],hd[u]=cnt;
e[++cnt].v=u,e[cnt].net=hd[v],hd[v]=cnt;
}
void dfs_first(int u)
{
for(re int i=hd[u],v;i;i=e[i].net)
{
v=e[i].v;
if(dep[v])continue;
dep[v]=dep[u]+1,fa[v]=u;
dfs_first(v);
}
}
void dfs_second(int u,int fa)
{
for(re int i=hd[u],v;i;i=e[i].net)
{
v=e[i].v;
if(v==fa)continue;
dis[v]=dis[u]+1;
dfs_second(v,u);
}
}
int main()
{
n=read(),m=read();
for(re int i=1;i<n;i++)add(read(),read());
dep[1]=1,dfs_first(1);
for(re int i=1,mid;i<=m;i++)
{
a[i]=read(),b[i]=read(),d[i]=read();
mid=(dep[a[i]]+dep[b[i]]-d[i]+1)>>1;
if(mid>ma)ma=mid,mx=a[i],my=b[i];
}
if(dep[mx]>dep[my])swap(mx,my);
for(;dep[mx]!=ma;)mx=fa[mx];
dfs_second(mx,0);
for(re int i=1;i<=m;i++)
if(dis[a[i]]+dis[b[i]]>d[i])return puts("NO"),0;
return printf("%d",mx),0;
}