iwtgm-6

题目链接

A.

感觉1和2非常神奇,可以得到非常神奇的结论,
自我猜想可能是因为首先它们的值很小,那么可以表示的范围非常大,
然后可以改变奇偶性,范围就更大了

这题的结论就是连续1的个数/3

先特判第一步是1一定有一个贡献

然后加上后面连续1的个数/3

void solve()
{
    int n,ans;cin>>n>>ans;
    int cnt=0;
    for(int i=1,a;i<n;i++){
        cin>>a;
        if(a==1)++cnt;
        else{
            ans+=cnt/3;
            cnt=0;
        }
    }
    cout<<ans+cnt/3<<endl;
}

B.

把数组离散化,只对端点进行处理,
头端点的值为1,尾端点的值为-1,尾端点的位置要+1,(因为也算在覆盖范围内)把所有端点打乱按位置排序
一个变量cnt记录当前覆盖的线段个数,tmp记录的是上一个端点的位置
两个端点的差是cnt的贡献

int n;
ll l,r,ans[N],cnt,tmp;
map<ll,ll>m;
void solve()
{
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>l>>r;
        m[l]++;m[++r]--;
    }
    for(auto tt:m){
        ans[cnt]+=tt.first-tmp;
        tmp=tt.first;
        cnt+=tt.second;
    }
    for(int i=1;i<=n;i++)cout<<ans[i]<<' ';
}

C.

树上差分,
前缀和就是当前节点的答案,
特定深度的节点很多,但我们dfs是在一个子树内进行的,到回溯的时候把差分数组归位(影响消去)就不会对其他子树产生影响

#define pii pair<ll,ll>
ll n,q,dep[N],val[N],ans[N];//深度数组,差分数组,答案数组
vector<int>g[N];//树
vector<pii>vec[N];//操作
void dfs(ll u,ll pre,ll sum){
    sum+=val[dep[u]];//差分数组求前缀和就是原数组,这里就是单个点的值
    for(int i=0;i<vec[u].size();i++){//把影响算入
        sum+=vec[u][i].second;
        if(dep[u]+vec[u][i].first+1<=n)val[dep[u]+vec[u][i].first+1]-=vec[u][i].second;//差分
    }
    ans[u]=sum;//可以有答案了,因为影响是对子树的影响,现在该节点已经是根了,别人无法再对它产生影响
    for(int i=0;i<g[u].size();i++){
        int v=g[u][i];
        if(v==pre)continue;
        dep[v]=dep[u]+1;//深度
        dfs(v,u,sum);
    }
    for(int i=0;i<vec[u].size();i++){
        if(dep[u]+vec[u][i].first+1<=n)val[dep[u]+vec[u][i].first+1]+=vec[u][i].second;//消除影响,不影响其他子树
    }
}
void solve()
{
    cin>>n;
    for(int i=1,x,y;i<n;i++){
        cin>>x>>y;
        g[x].push_back(y);
        g[y].push_back(x);
    }
    cin>>q;
    for(int i=1,x,y,z;i<=q;i++){
        cin>>x>>y>>z;
        vec[x].push_back({y,z});
    }
    dep[1]=1;
    dfs(1,0,0);
    for(int i=1;i<=n;i++)cout<<ans[i]<<' ';
}
posted @ 2023-11-02 13:23  WW爆米花  阅读(8)  评论(0编辑  收藏  举报