每一年都奔走在自己热爱里

没有人是一座孤岛,总有谁爱着你

AtCoder Beginner Contest 294(E,F,G)

AtCoder Beginner Contest 294(E,F,G)

E (思维,双指针)

E

这个题的大意就是有一个2L列的网格,每个格子里面都有不同的数字,但是它的输入方式不是一个一个输入的,而是从第一个开始,枚举每个数在这一段的数量,(比如a1=2,L1=3,那么此时就已经有了一个长度为3的数列(222)了

我们要求的是第一行和第二行相同的数的数量

一个一个去找显然是不太可能(L的范围有一点大),但是题目告知每行的段的数量只有1e5的范围,而且每一行都是从头开始,都是有序的,那么我们可以定义两个指针,一个指向第一行上一次的还未使用完的段,一个是指向第二行的一段,只要这两个指针指向的那一个段里面的值一样,那么就可以获得这两个段的交集的数量的贡献,就算是不一样的,但是第二行的指针指向的线段还是需要减少的,(这个交集里面的数一定是不一样的,贡献一定为0)

这样的操作两个指针最多会到1e5,不会超时

具体看代码

#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include<cmath>
#include <bitset>
#include <unordered_map>
using namespace std;
const int maxn=4e5+10;
const int mod=998244353;
const double eps=1e-7;
#define int long long 
#define ios  ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
int n,m,L;
int a[maxn],b[maxn];
signed main ()
{
    cin>>L>>n>>m;
    int res=0;
    for (int i=1;i<=n;i++)
    {
        cin>>a[i]>>b[i];
    }
    int now=1;
    for (int i=1;i<=m;i++)
    {
        int v,l;
        cin>>v>>l;
        while (l)
        {
            int len=min(l,b[now]);
            if(v==a[now]) res+=len;
            b[now]-=len;
            l-=len;
            if(!b[now]) now++;
        }
    }
    cout<<res<<"\n";
    system ("pause");
    return 0;
}

F(二分)

F

这个题目大意是有两个人,他们各自有nm种配料组合(xy),现在我们要让这两个人从中选择出任意一种组合和另外一个搭配,搭配后的浓度公式如下

d=x1+x2y1+y2+x1+x2×100

求第k高的浓度大小为多少

对于答案,我们知道一定是在01之间寻找

所以我们可以用到二分,但是check函数该怎么写呢

假设此时的第k大的浓度为mid

那么我们可以发现存在k1个这样的式子xi+xjxi+xj+yi+yj>mid

一个一个寻找还是不太好

我们可以试着把上面那个式子移项,把ixy移到一边

变成了

(1mid)×ximid×yi>(mid1)×xj+mid×yj

然后求这样的式子有多少个,我们可以分别存下大于号左右两边的式子,排序,然后和上一题类似的求出满足以上式子的数量,记录为cnt

cnt>k,那么这个一定是不满足的,浓度低了

#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include<cmath>
#include <bitset>
#include <unordered_map>
using namespace std;
const int maxn=4e5+10;
const int mod=998244353;
const double eps=1e-12;
#define int long long 
#define ios  ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
int n,m,k;
double x[maxn],y[maxn],xx[maxn],yy[maxn];
bool check(double now)
{
    vector<double>a(n+1),b(m+1);
    for (int i=1;i<=n;i++)
    {
        a[i]=(1.0-now)*x[i]-now*y[i];
    }
    for (int i=1;i<=m;i++)
    {
        b[i]=(now-1.0)*xx[i]+now*yy[i];
    }
    sort(a.begin()+1,a.end());
    sort(b.begin()+1,b.end());
    int cur=1,cnt=0;
    for (int i=1;i<=n;i++)
    {
        while (cur<=m&&b[cur]<a[i])
        {
            cur++;
        }
        cnt+=(cur-1);
        if(cnt>k) return false;
    }
    return cnt<=k;
}
signed main ()
{
    cin>>n>>m>>k;
    for (int i=1;i<=n;i++)
    {
        cin>>x[i]>>y[i];
    }
    for (int i=1;i<=m;i++)
    {
        cin>>xx[i]>>yy[i];
    }
    double l=0,r=1.0;
    k--;
    double ans;
    while (r-l>eps)
    {
        double mid=(l+r)/2.0;
        if(check(mid))
        {
            r=mid;
            ans=mid;
        }
        else l=mid;
    }
    ans*=100.0;
    printf("%.10lf\n",ans);
    system ("pause");
    return 0;
}

G(lca,树状数组)

G

这个题首先是给你n1条边,每一条边都会有一个权值,然后会有q个操作,有两种操作类型

1,输入1,i,w,代表把第i条边的权值更新为w

2,输入2,x,y,需要我们输出这两个点的路径的权值和

假如没有修改权值的话,我们或许可以直接dis(x)+dis(y)dis(lca(x,y)),但是还要修改里面的边的值,每次都要进行dfs就很不现实,故我们可采用树状数组,把每一个点对这些路径的贡献都转化为dfs的遍历顺序存放在树状数组里面

如何记录每一个点的影响范围呢

我们可以记录每一个点的dfn1序和一另外一个dfn2序,在dfn1dfn2这一段里面,就是这一个点的贡献

然后对于修改一条边的权值,我们要怎样修改呢

我们可以先这样看,从1u的距离为dis,而uv的距离为val,那么从1v的距离为dis+val,所以我们可以改变(u,v)这一条边的值只会影响v所连接的路径,而不会影响到u

所以我们只需要改变v点的影响范围的值即可,还要记得更新边的值,防止下一次又是更新这一条边,但是这里面存的不是最新的值

然后lca我这里用了倍增写法,可以参考模板

#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include<cmath>
#include <bitset>
#include <unordered_map>
using namespace std;
const int maxn=2e5+10;
const int mod=998244353;
const double eps=1e-12;
#define int long long 
#define ios  ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
struct node
{
    int next,to,val,id;
}e[maxn<<2];
int bit[maxn<<2];
int head[maxn],cnt;
int dfn1[maxn],dfn2[maxn],f[maxn][31];
int idx[maxn];
int dep[maxn];
int u[maxn],v[maxn],val[maxn];
int tim;
int s=30;
int n,q;
void add(int u,int v,int val,int id)
{
    e[++cnt].next=head[u];
    e[cnt].to=v;
    e[cnt].val=val;
    e[cnt].id=id;
    head[u]=cnt;
    return ;
}
void dfs(int u,int fa)
{
    dfn1[u]=++tim;
    f[u][0]=fa;
    for (int i=1;i<s;i++)
    {
        f[u][i]=f[f[u][i-1]][i-1];
    }
    for (int i=head[u];i;i=e[i].next)
    {
        int v=e[i].to;
        if(v==fa) continue;
        int id=e[i].id;
        dep[v]=dep[u]+1;
        dfs(v,u);
        idx[id]=v;
    }
    dfn2[u]=tim;
    return ;
}
int lca(int u,int v)
{
    if(dep[u]<dep[v]) swap(u,v);
    int dlt=dep[u]-dep[v];
    for (int i=0;i<s;i++)
    {
        if((dlt>>i)&1)u=f[u][i];
    }
    if(u==v) return u;
    for (int i=s-1;i>=0;i--)
    {
        if(f[u][i]!=f[v][i])
        {
            u=f[u][i];
            v=f[v][i];
        }
    }
    return f[u][0];
}
int lowbit(int x)
{
    return x&(-x);
}
void update(int x,int val)
{
    while (x<=n)
    {
        bit[x]+=val;
        x+=lowbit(x);
    }
    return ;
}
int query(int x)
{
    int res=0;
    while (x)
    {
        res+=bit[x];
        x-=lowbit(x);
    }
    return res;
}
signed main ()
{
    cin>>n;
    for (int i=1;i<n;i++)
    {
        cin>>u[i]>>v[i]>>val[i];
        add(u[i],v[i],val[i],i);
        add(v[i],u[i],val[i],i);
    }
    dfs(1,0);
    for (int i=1;i<n;i++)
    {
        update(dfn1[idx[i]],val[i]);
        update(dfn2[idx[i]]+1,-val[i]);
    }
    cin>>q;
    while (q--)
    {
        int op,x,y;
        cin>>op>>x>>y;
        if(op==1)
        {
            int now=idx[x];
            update(dfn1[now],y-val[x]);
            update(dfn2[now]+1,val[x]-y);
            val[x]=y;
        }
        else 
        {
          //  cout<<"ans  ";
            int res=query(dfn1[x])+query(dfn1[y])-2*query(dfn1[lca(x,y)]);
            cout<<res<<"\n";
        }
    }
    system ("pause");
    return 0;
}
posted @   righting  阅读(38)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示