百度有一位非常有名的大科学家,这位大科学家有很多藏书。
大科学家有一个图书馆,所以放书的容量也随之增加了,图书馆可以看成一个长度为 NN 的序列,一开始里面放着 NN 本书,每本书都记载了一个特定元素的信息,书中的元素各不相同。
大科学家会先进行若干次研究,最后进行一次科学实验,这次实验需要选取一些元素放在一起来进行。每次研究,大科学家会从图书馆中的某些位置抽出一些书来看,然后得出“如果 xx 位置上的书对应的元素被拿来做实验了,那么区间 [l,r][l,r] 位置上的书对应的元素也必须拿来做实验,否则会爆炸”这样的结论。
大科学家有不止 NN 本书(也就是说世界上有不止 NN 种元素),但是他自己没时间给图书馆换书,所以他雇了一个实习生,这个实习生会时不时地拿出一本 从来没被放入图书馆的书,然后替换掉图书馆中某个位置原来的书(所以对于大科学家得到的两次看似一样的研究结果,可能由于图书馆中的书被换了,它们的实质内容可能不一样)。
每本书还记载着对应元素的非负污染值,大科学家希望在完成一次科学实验的前提下(不能不选任何元素),这次实验的总污染值最小。作为一个旁观者,你能看到科学家做的所有研究结果以及实习生换书的顺序,然后你需要告诉大科学家,这个最小总污染值是多少。
由于大科学家精力有限,所以它只能得出不多的实验结论(具体参见数据范围)。
输入格式
第一行一个正整数 NN,代表图书馆的容量。
接下来一行 NN 个数,第 ii 个非负整数 a_iai 代表最开始图书馆中第 ii 本书所描述的元素的污染值。
接下来一行一个整数 MM,代表事件的总数。
接下来 MM 行,每行代表一个事件:
若为 00 xx yy,代表实习生拿了一本新书替换了 xx 位置的书,新书对应元素的污染值为 yy。
若为 11 xx ll rr,代表大科学家得到了新的结果,如果 xx 位置的书对应的元素加入了实验,那么 [l,r][l,r] 区间内的书对应的元素都必须拿来做实验。
保证大科学家的书籍总数 (N+(N+ 新书数量 ) \le 10^5)≤105。
每个元素的污染值 0 \le (a_i,y) \le 10^90≤(ai,y)≤109。
保证 1 \le x \le N1≤x≤N,1 \le l \le r \le N1≤l≤r≤N,M \le 10^5M≤105。
由于大科学家的精力有限,做不了太多的实验,所以我们保证 \sum(r-l+1) \le 10^5∑(r−l+1)≤105。
输出格式
输出一个整数,代表最小总污染值。
样例解释
一开始书架上有 55 本书,我们记这些元素的编号顺次为 1,2,3,4,51,2,3,4,5,他们的污染值分别为 1,10,100,1000,100001,10,100,1000,10000。
一共有 44 个事件:
大科学家发现,选了元素 11 就必须选元素 3,43,4。
大科学家发现,选了元素 33 就必须选元素 55。
实习生拿了一本新书,我们记这个新元素的编号为 66,他的污染值为 00,替换掉现在书架上的第 33 本书,现在书架上的 55 本书对应元素为 1,2,6,4,51,2,6,4,5。
大科学家发现,选了元素 66(因为它在位置 33 上)就必须选元素 1,21,2。
于是在所有可能的方案中,单选一个元素 22 来做实验是总污染值最小的,因为如果选择元素 11 或元素 66,都存在一些绑定关系使得总污染值不可能比 1010 更小。
题目链接:https://nanti.jisuanke.com/t/26982
题解:我们直接将所有可以组成强连通分量的点缩成一个点,这样最终的无向图会变成一个有向无环图
然后我们对于所有出度为0的点找一波权值最小值就好啦
#include<stack>
#include<vector>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
typedef long long ll;
#define maxn 100005
stack<ll>s;
vector<ll>q[maxn],q1[maxn];
ll in[maxn],dfn[maxn],low[maxn],t,cnt,len;
ll vis[maxn],num,belong[maxn],val[maxn],a[maxn],cost[maxn],out[maxn];
void tarjan(int u)
{
ll i,now;
dfn[u]=low[u]=++t;
s.push(u);in[u]=1;vis[u]=1;
for(i=0;i<q[u].size();i++)
{
int v=q[u][i];
if(vis[v]==0)
{
tarjan(v);
low[u]=min(low[u],low[v]);
continue;
}
if(belong[v]==0)
low[u]=min(low[u],dfn[v]);
}
if(dfn[u]==low[u])
{
num++;
while(s.empty()==0)
{
now=s.top();
s.pop();
in[u]=0;
belong[now]=num;
cost[num]+=val[now];
if(now==u)
break;
}
}
}
int main(void)
{
ll n,i,j,m,x,y,z,w;
scanf("%lld",&n);
for(i=1;i<=n;i++)
{
scanf("%lld",&val[i]);
a[i]=i;
}
len=n;
scanf("%lld",&m);
while(m--)
{
scanf("%lld",&x);
if(x==1)
{
scanf("%lld%lld%lld",&y,&z,&w);
for(int i=z;i<=w;i++)
{
if(i==y)
continue;
q[a[y]].push_back(a[i]);
}
}
else
{
scanf("%lld%lld",&y,&z);
a[y]=++len;val[len]=z;
}
}
for(i=1;i<=len;i++)
if(vis[i]==0)
tarjan(i);
for(i=1;i<=len;i++)
for(j=0;j<q[i].size();j++)
{
int v=q[i][j];
if(belong[i]!=belong[v])
{
q1[belong[i]].push_back(belong[v]);
out[belong[i]]++;
}
}
ll ans=5e18;
for(int i=1;i<=len;i++)
{
if(out[belong[i]]==0)
ans=min(ans,cost[belong[i]]);
}
printf("%lld\n",ans);
return 0;
}
10