Codeforces Round #826 (Div. 3)

Codeforces Round #826 (Div. 3)

E. Sending a Sequence Over the Network

题目大意

假设一个数组a=[1,2,3,4,5],将其分割为,[1],[2,3],[4,5,6],以此构建一个新数组,构建的原则是,分割的各部分的长度需要在该段的左边或右边,例如分割为b = [1,1,2,2,3,3,4,5,6]

给定一个数组b,求是否有合法的a

分析

是一道不难的DP,写的时候nt了,写了好久。

我们来简单说一下思路。我们用dp[i]来表示第i个点结尾可以得到合法解。

我们考虑每个数字,如果将其作为表示某个段的长度,则其覆盖的要不是前边的,要不是后面。

则我们考虑如果覆盖前边,则若dp[i-a[i]-1]是合法的,则当前点一定合法。

然后去看如果当前点覆盖后边,去更新后面的点为dp[i+a[i]+1]

结束啦。

AC_code

#include <bits/stdc++.h>
#define fi first    
#define se second    
#define endl '\n'
#define ios ios::sync_with_stdio(false); cin.tie(0), cout.tie(0)
using ll = long long;
using namespace std;
const int N = 1e5 + 10,M = N*2;
   
void solve() {
    int n;cin>>n;
    vector<int> b(n);
    vector<int> f(n+1);
    for(auto &x:b) cin>>x;
    f[0] = 1;
    for(int i=0;i<=n;i++)
    {
        if(i&&i-1-b[i-1]>=0) f[i] |= f[i-1-b[i-1]];
        if(i<n&&i+b[i]+1<=n) f[i+b[i]+1] |= f[i];
    }
    if(f[n]) cout<<"YES\n";
    else cout<<"NO\n";
}
 
int main() 
{
    ios;
    int T=1;
    cin>>T;
 
    while(T -- ) {
        solve();
    }
 
    return 0;
}

F. Multi-Colored Segments

题目大意

给定一些线段,其中每个线段有一个颜色,问每一个线段距离其最近的不同颜色的线段的距离。

分析

倒也不难,不过有一些麻烦。

我们来看看。

我们首先来看看不考虑颜色

我们建立权值线段树,接下来对于每个线段,是否有别的线段与其相交,若有则为0。

若无,我们用multisetL,R存起来所有的左端点和右端点。直接寻找除该线段外的最近的其他线段。

具体的就是,对于该线段的左端点,在R中寻找最近的右端点,对于该线段的右端点,在L中寻找最近的左端点。

有颜色

也很简单,我们直接对于每种颜色单独操作,当遍历该颜色的线段时,将所有的该颜色的线段影响全部消除。

小细节

我们可以看到权值很大,因此我们直接建立动态开点线段树。当然也可以进行离散化后的线段树,当然也可以离散化后的树状数组。

我是为了练习,写的动态开点线段树,赛时当然选择离散化后的树状数组,会好写很多。

AC_code

#include<bits/stdc++.h>
#define ios ios::sync_with_stdio(false); cin.tie(0), cout.tie(0)
using namespace std;
const int N = 2e5 + 10,inf = 0x3f3f3f3f;

struct Seg
{
    int l,r,c,id;
}segs[N];
vector<int> col[N];
struct Node
{
    int l,r;
    int sum,add;
}tr[N<<6];
int n,idx,root,ans[N];

void pushup(int u)
{
    tr[u].sum = tr[tr[u].l].sum + tr[tr[u].r].sum;
}

void pushdown(int u,int l,int r)
{
    if(!tr[u].l) tr[u].l = ++idx;
    if(!tr[u].r) tr[u].r = ++idx;
    auto &root = tr[u],&left = tr[tr[u].l],&right = tr[tr[u].r];
    int mid = l + r >> 1;
    if(root.add)
    {
        left.add += root.add;
        right.add += root.add;
        left.sum += (mid - l + 1)*root.add;
        right.sum += (r - mid)*root.add;
        root.add = 0;
    }
}

void modify(int &u, int l, int r, int x, int y, int v) {
    if(!u) u = ++ idx;
    if(x <= l && y >= r) {
        int len = r - l + 1;
        tr[u].sum += len * v;
        tr[u].add += v;
        return ;
    }
    pushdown(u, l, r);
    int mid = l + r >> 1;
    if(x <= mid) modify(tr[u].l, l, mid, x, y, v);
    if(y > mid) modify(tr[u].r, mid + 1, r, x, y, v);
    pushup(u);
}
int query(int u,int l,int r,int L,int R)
{
    if(R<l||L>r) return 0;
    if(!u) return 0;
    if(L<=l&&r<=R) return tr[u].sum;
    pushdown(u,l,r);
    int mid = l + r >> 1;
    return query(tr[u].l,l,mid,L,R) + query(tr[u].r,mid+1,r,L,R);
}

void solve()
{
    cin>>n;
    multiset<int> L,R;
    for(int i=1;i<=n;i++) col[i].clear();
    for(int i=1;i<=idx;i++) tr[i].l = tr[i].r = tr[i].sum = tr[i].add = 0;
    root = idx = 0;
    for(int i=1;i<=n;i++)
    {
        auto &[l,r,c,id] = segs[i];
        cin>>l>>r>>c;
        id = i;ans[i] = inf;
        col[c].push_back(i);
        L.insert(l),R.insert(r);
        modify(root,1,inf,l,r,1);
    }
    for(int i=1;i<=n;i++)
    {
        for(auto it:col[i])
        {
            auto &[l,r,c,id] = segs[it];
            L.erase(L.lower_bound(l));
            R.erase(R.lower_bound(r));
            modify(root,1,inf,l,r,-1);
            // cout<<query(root,1,inf,l,r)<<" "<<l<<" "<<r<<endl;
        }
        for(auto it:col[i])
        {
            auto &[l,r,c,id] = segs[it];
            int res = query(1,1,inf,l,r);
            // cout<<l<<" "<<r<<" "<<c<<" "<<id<<" ";
            // cout<<res<<endl;
            if(res) 
            {
                ans[id] = 0;
                continue;
            }
            auto it1 = L.lower_bound(r),it2 = R.lower_bound(l);
            if(it1 != L.end()) 
            {
                ans[id] = min(ans[id],max(0,*it1-r));
                // cout<<ans[id]<<' '<<id<<endl;
            }
            if(it2 != R.begin()) 
            {
                ans[id] = min(ans[id],max(0,l - *--it2));
                // cout<<ans[id]<<' '<<id<<endl;
            }
        }
        for(auto it:col[i])
        {
            auto &[l,r,c,id] = segs[it];
            L.insert(l);R.insert(r);
            modify(root,1,inf,l,r,1);
        }
    }
    for(int i=1;i<=n;i++) cout<<(ans[i]==inf?0:ans[i])<<' ';
    cout<<'\n';
}

int main()
{
    ios;
    int T;cin>>T;
    while(T--) solve();
    return 0;
}

posted @ 2022-10-27 15:53  艾特玖  阅读(48)  评论(1)    收藏  举报