Codeforces Round 816 (Div. 2)(D拆位图论构造 E斜率优化)

C:直接单独算每个位置的贡献,如果当前位置和前面位置重复了,那么前面就没选的位置了

修改的时候只要重新算i和i+1位置即可

#include<bits/stdc++.h>
using namespace std;
const int N=3e5+10,M=2*N,mod=1e9+7;
#define int long long
#define uLL unsigned long long
const long long inf=1e18;
typedef pair<int,int> PII;
typedef long long LL;
using node=tuple<int,int,int>;
int n,m,k;
int a[N];

int calc(int i){
    int res=0;
    int k=n-i+1;
    if(a[i]==a[i-1]) return k;
    return (n-i+1)*(i);
}
void solve()
{
    cin>>n>>m;
    int s=0;
    for(int i=1;i<=n;i++) cin>>a[i];
    for(int i=1;i<=n;i++){
            s+=calc(i);

    }
    a[n+1]=0;
    
    while(m--){
        int x,y;cin>>x>>y;
        s-=calc(x);
        s-=calc(x+1);
        a[x]=y;
        s+=calc(x);
        s+=calc(x+1);
        cout<<s<<"\n";
        //cout<<calc((int)(st.size()))<<"\n";
    }
} 

signed main(){
	cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);
	int t=1;
//	cin>>t;
	
	while(t--) solve();
	return 0;
}

D:

拆位,考虑字典序最小,让开头的数能等于0就等于0

要先把一定是0的数和u==v这种确定的数先填了,后面根据字典序填即可

#include<bits/stdc++.h>
using namespace std;
const int N=3e5+10,M=2*N,mod=1e9+7;
#define int long long
#define uLL unsigned long long
const long long inf=1e18;
typedef pair<int,int> PII;
typedef long long LL;
using node=tuple<int,int,int>;
int n,m,k;
int a[N];
vector<PII> g[N];
int now[N];

void solve()
{
    cin>>n>>m;
    vector<array<int,3>> a(m);
    for(auto&i:a){
        cin>>i[0]>>i[1]>>i[2];
        g[i[0]].emplace_back(i[1],i[2]);
        g[i[1]].emplace_back(i[0],i[2]);
    }
    vector<int> res(n+10);
    for(int i=30;i>=0;i--)
    {
        memset(now,-1,sizeof(now));
        for(int j=1;j<=n;j++){
            for(auto [v,z]:g[j]){
               
                if(v==j){
                    now[j]=(z>>i&1);continue;
                } 
                if(z>>i&1) continue;
                now[j]=now[v]=0;
            }
        }
        for(int j=1;j<=n;j++)
        {
            if(g[j].size()==0)
            {
                now[j]=0;
            }
            if(now[j]!=-1) continue;
            for(auto [v,z]:g[j])
            {
                if(now[v]==0)//另一个固定了,j只能是1
                {
                    now[j]=1;
                    break;
                }
            }
            if(now[j]==-1)
            {
                for(auto [v,z]:g[j])
                {
                    now[v]=1;
                }
                now[j]=0;
            }
        }    
        for(int j=1;j<=n;j++)
        res[j]+=(now[j])*(1<<i);
    }
    for(int i=1;i<=n;i++) cout<<res[i]<<" ";
} 

signed main(){
	cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);
	int t=1;
	//cin>>t;
	
	while(t--) solve();
	return 0;
}

E:

直接斜率优化

考虑每层k进行斜率优化,毕竟转移只会从i-1转移到i层

f[i]=min(f[j]+(i-j)^2)

根据斜率优化式子

f[i]=f[j]+i*i-2*i*j+j*j

f[j]+j*j=2*i*j+f[i]-i*i

y=f[j]+j*j

k=2*i

b=f[i]-i*i

y=kx-b

当i确定的时候让b最小,f[i]一定最小

直接维护凸包即可

#include<bits/stdc++.h>
using namespace std;
const int N=3e5+10,M=2*N,mod=1e9+7;
#define int long long
#define uLL unsigned long long
const long long inf=1e18;
typedef pair<int,int> PII;
typedef long long LL;
using node=tuple<int,int,int>;
int n,m,k;
int a[N];
vector<PII> g[N];
int now[N];

void solve()
{
    cin>>n>>m;
    vector<array<int,3>> a(m);
    for(auto&i:a){
        cin>>i[0]>>i[1]>>i[2];
        g[i[0]].emplace_back(i[1],i[2]);
        g[i[1]].emplace_back(i[0],i[2]);
    }
    vector<int> res(n+10);
    for(int i=30;i>=0;i--)
    {
        memset(now,-1,sizeof(now));
        for(int j=1;j<=n;j++){
            for(auto [v,z]:g[j]){
               
                if(v==j){
                    now[j]=(z>>i&1);continue;
                } 
                if(z>>i&1) continue;
                now[j]=now[v]=0;
            }
        }
        for(int j=1;j<=n;j++)
        {
            if(g[j].size()==0)
            {
                now[j]=0;
            }
            if(now[j]!=-1) continue;
            for(auto [v,z]:g[j])
            {
                if(now[v]==0)//另一个固定了,j只能是1
                {
                    now[j]=1;
                    break;
                }
            }
            if(now[j]==-1)
            {
                for(auto [v,z]:g[j])
                {
                    now[v]=1;
                }
                now[j]=0;
            }
        }    
        for(int j=1;j<=n;j++)
        res[j]+=(now[j])*(1<<i);
    }
    for(int i=1;i<=n;i++) cout<<res[i]<<" ";
} 

signed main(){
	cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);
	int t=1;
	//cin>>t;
	
	while(t--) solve();
	return 0;
}
相关推荐
ShareBeHappy_Qin18 分钟前
MySQL —— Innodb 索引数据结构
数据结构·数据库·mysql·innodb索引数据结构
闻缺陷则喜何志丹41 分钟前
【C++ 滑动窗口】2134. 最少交换次数来组合所有的 1 II
c++·算法·leetcode·力扣·交换·组合·最少
gsgbgxp43 分钟前
C++类中的const成员变量和const成员函数
开发语言·c++·算法
丶Darling.1 小时前
Day41 | 动态规划 :完全背包应用 完全平方数&&单词拆分(类比爬楼梯)
算法·动态规划·dp·lambda·记忆化搜索·回溯·c++\
地平线开发者1 小时前
征程 6 工具链性能分析与优化 2|模型性能优化建议
算法·自动驾驶
Duck Bro1 小时前
数据结构:顺序表(动态顺序表)
c语言·数据结构·c++·学习·算法
DK221512 小时前
机器学习系列-----主成分分析(PCA)
人工智能·算法·机器学习
oliveira-time2 小时前
爬虫学习8
开发语言·javascript·爬虫·python·算法
jinmo_C++3 小时前
数据结构——链表(带有头节点)
数据结构·链表
点云侠3 小时前
二维椭圆拟合算法及推导过程
开发语言·c++·算法·计算机视觉·matlab