zoukankan      html  css  js  c++  java
  • 【计蒜客】百度科学家(困难)

    【题目】百度科学家(困难)
    【题意】给定n个非负整数,最终需要选择一个数字集合。m次操作,修改一个非负整数,或规定选择第x个数字则必须选择区间[l,r]内的数字。最终求非空数字集合的最小值。(n,m leq 10^5)
    需要特别注意,被替换了的非负整数也是可以选择的。每一个非负整数都是本质不同的,区间[l,r]内的数字指的是当前情况下区间[l,r]内的数字。
    【算法】主席树优化建图+Tarjan缩点
    【题解】考虑朴素做法,每次规定点x向区间内的点连边,修改就建新的点替换进序列,最后Tarjan缩点后求出度为0的点权最小值。这样边数是(O(nm))的。
    因为向区间连边很容易想到用主席树优化。每次修改在原来的基础上新增一条链,父亲向儿子连边。每次规定用当前最后一个在位置x的点编号向区间连边。
    复杂度(O(n log n))
    【注意】
    1.每次新建链都需要向左右儿子连边。不要连向0。
    2.边数组开3倍。
    3.有向图的Tarjan算法不用判断反向边。

    #include<cstdio>
    #include<algorithm>
    #define ll long long
    using namespace std;
    bool isdigit(char c){return c>='0'&&c<='9';}
    int read(){
    	int s=0,t=1;char c;
    	while(!isdigit(c=getchar()))if(c=='-')t=-1;
    	do{s=s*10+c-'0';}while(isdigit(c=getchar()));
    	return s*t;
    }
    const int maxn=100010,N=1800010;
    int dfn[N],low[N],st[N],dfsnum,cnt,tot,first[N],col[N],sz,v[maxn],top,n,m,rt,ou[N];
    ll num[N];
    struct edge{int u,v,from;}e[N*3];//three
    void ins(int u,int v){tot++;e[tot].u=u;e[tot].v=v;e[tot].from=first[u];first[u]=tot;}
    struct tree{int l,r,s;}t[N];
    void insert(int &x,int y,int l,int r,int k,int p){
    	x=++sz;t[x]=t[y];
    	if(l==r){t[x].s=p;v[k]=x;return;}
    	int mid=(l+r)>>1;
    	if(k<=mid)insert(t[x].l,t[y].l,l,mid,k,p);
    	else insert(t[x].r,t[y].r,mid+1,r,k,p);
    	if(t[x].l)ins(x,t[x].l);if(t[x].r)ins(x,t[x].r);//0
    }
    void tarjan(int x){
    	dfn[x]=low[x]=++dfsnum;st[++top]=x;
    	for(int i=first[x];i;i=e[i].from){//fan???
    		if(!dfn[e[i].v]){
    			tarjan(e[i].v);
    			low[x]=min(low[x],low[e[i].v]);
    		}
    		else if(!col[e[i].v])low[x]=min(low[x],dfn[e[i].v]);
    	}
    	if(dfn[x]==low[x]){
    		cnt++;
    		while(st[top]!=x)col[st[top--]]=cnt;
    		col[st[top--]]=cnt;
    	}
    }
    void modify(int k,int l,int r,int L,int R,int x){
    	if(L<=l&&r<=R)return void(ins(x,k));
    	int mid=(l+r)>>1;
    	if(L<=mid)modify(t[k].l,l,mid,L,R,x);
    	if(R>mid)modify(t[k].r,mid+1,r,L,R,x);
    }
    int main(){
    	n=read();
    	for(int i=1;i<=n;i++)insert(rt,rt,1,n,i,read());
    	m=read();
    	while(m--){
    		int kind=read();
    		if(!kind){
    			int x=read(),y=read();
    			insert(rt,rt,1,n,x,y);
    		}
    		else{
    			int x=read(),l=read(),r=read();
    			modify(rt,1,n,l,r,v[x]);
    		}
    	}
    	for(int i=1;i<=sz;i++)if(!dfn[i])tarjan(i);
    	for(int i=1;i<=sz;i++)num[col[i]]+=t[i].s;//long long
    	for(int i=1;i<=tot;i++)if(col[e[i].u]!=col[e[i].v])ou[col[e[i].u]]++;
    	ll ans=1ll<<60;
    	for(int i=1;i<=cnt;i++)if(!ou[i]&&ans>num[i])ans=num[i];
    	printf("%lld",ans);
    	return 0;
    }
  • 相关阅读:
    v-bind绑定属性
    vue 第二次学习笔记 v-once v-html
    P4428-[BJOI2018]二进制【树状数组,set】
    P5180-[模板]支配树
    《架构之美》阅读笔记一
    Python基础04----条件控制
    Tensorflow2.0笔记33——Keras 来搭建神经网络的“八股”套路
    每周总结
    架构漫谈阅读笔记01
    Tensorflow2.0笔记32——卷积神经网络
  • 原文地址:https://www.cnblogs.com/onioncyc/p/9030618.html
Copyright © 2011-2022 走看看