通过子任务1、3十分显然,子任务4实际上就是线段树,和我下午写的[SDOI2015]道路修建一模一样,堪称“我抄我自己”,不会的可以先做一下这个题。

然后考虑正解,参考了zhoushuyu的博客,首先可以对前i列做MST,就是把前i-1列和第i列合并起来,而这时候只需要把第1和第i列的点作为关键点建立虚树,虚树边权为原树路径最大值,然后每次O(n)对虚树合并即可。后缀也同样做一遍即可。查询时,就是把整张图分成两半,同样只需要维护前后缀的左右两列建立虚树即可,复杂度O(n(m+q)logn)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=;
struct edge{int u,v,w;};
bool operator<(edge a,edge b){return a.w<b.w;}
int n,m,Q,lim,tot,cnt,d1[N][],d2[N][],fa[N],hd[N],v[N],nxt[N],w[N],vis[N];
ll ans;
unsigned int SA,SB,SC;
vector<edge>G;
struct MST{
int tot;ll sum;
vector<edge>G;
MST(){}
MST(int*c)
{
tot=n,sum=;
for(int i=;i<n;i++)G.push_back((edge){i,i+,c[i]});
}
}pre[N],suf[N];
int getweight()
{
SA^=SA<<,SA^=SA>>,SA^=SA<<;
unsigned int t=SA;
SA=SB,SB=SC,SC^=t^SA;
return SC%lim+;
}
int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
void adde(edge x)
{
v[++cnt]=x.v,nxt[cnt]=hd[x.u],w[cnt]=x.w,hd[x.u]=cnt;
v[++cnt]=x.u,nxt[cnt]=hd[x.v],w[cnt]=x.w,hd[x.v]=cnt;
ans+=x.w;
}
bool dfs1(int u,int f)
{
int ret=;
for(int i=hd[u];i;i=nxt[i])if(v[i]!=f)ret+=dfs1(v[i],u);
vis[u]|=(ret>=),ret+=vis[u];
return ret;
}
void dfs2(int u,int f,int lst,int val)
{
if(vis[u])
{
if(lst)G.push_back((edge){vis[u],lst,val});
lst=vis[u],ans-=val,val=;
}
for(int i=hd[u];i;i=nxt[i])if(v[i]!=f)dfs2(v[i],u,lst,max(val,w[i]));
}
MST merge(MST a,MST b,int*c)
{
G.clear(),tot=a.tot+b.tot;
for(int i=;i<a.G.size();i++)G.push_back(a.G[i]);
for(int i=;i<b.G.size();i++)G.push_back((edge){b.G[i].u+a.tot,b.G[i].v+a.tot,b.G[i].w});
for(int i=;i<=n;i++)G.push_back((edge){a.tot-n+i,a.tot+i,c[i]});
sort(G.begin(),G.end());
for(int i=;i<=tot;i++)fa[i]=i,vis[i]=(i<=n||i>tot-n),hd[i]=;
ans=cnt=;
for(int i=;i<G.size();i++)
{
int u=find(G[i].u),v=find(G[i].v);
if(u!=v)adde(G[i]),fa[u]=v;
}
dfs1(,),cnt=;
for(int i=;i<=tot;i++)if(vis[i])vis[i]=++cnt;
G.clear(),dfs2(,,,);
MST ret;ret.tot=cnt,ret.sum=a.sum+b.sum+ans,ret.G=G;
return ret;
}
ll query(MST a)
{
ll ret=a.sum;
for(int i=;i<a.G.size();i++)ret+=a.G[i].w;
return ret;
}
int main()
{
scanf("%d%d%u%u%u%d",&n,&m,&SA,&SB,&SC,&lim);
for(int i=;i<=n;i++)for(int j=;j<=m;j++)d1[j][i]=getweight();
for(int i=;i<n;i++)for(int j=;j<=m;j++)d2[j][i]=getweight();
pre[]=MST(d2[]),suf[m]=MST(d2[m]);
for(int i=;i<m;i++)pre[i]=merge(pre[i-],MST(d2[i]),d1[i-]);
for(int i=m-;i>;i--)suf[i]=merge(MST(d2[i]),suf[i+],d1[i]);
scanf("%d",&Q);
while(Q--)
{
int l,r;scanf("%d%d",&l,&r);
printf("%lld\n",query(merge(suf[r+],pre[l-],d1[m])));
}
}

最新文章

  1. 异步Socket 客户端部分
  2. php中的gethostbyname函数有问题
  3. delay() .split()
  4. 最小割 总结&amp;&amp;做题记录
  5. Python单元测试框架之pytest -- 生成测试报告
  6. ubuntu 14 安装 JDK
  7. DevExpress GridControl 使用方法技巧 总结 收录整理
  8. mongodb 新建用户 -摘自网络
  9. Django学习(三) Django模型创建以及操作
  10. poj 1905 Expanding Rods 二分
  11. mysql的登录和备份
  12. java 集合之实现类ArrayList 和 LinkedList
  13. java.lang.OutOfMemoryError: PermGen space有效解决方法
  14. Spring py登陆模块(包含 记录登陆时间,记录ip,增加积分)
  15. Spring中用了哪些设计模式
  16. git 命令的使用
  17. boost.property_tree解析xml的帮助类以及中文解析问题的解决(转)
  18. GPUImage中饱和度调整的实现——GPUImageSaturationFilter
  19. Linux - 更改软件源
  20. 常用python包(依赖)Ubuntu下

热门文章

  1. core_cm4.h(129): error: #35: #error directive: &quot;Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)&quot;
  2. 查看 vps 进程网络流量
  3. 吴裕雄--天生自然TensorFlow2教程:合并与分割
  4. SASS - 函数
  5. localStorage中使用json
  6. 一天一个设计模式——工厂方法(FactoryMethod)模式
  7. choice接口、同花顺使用
  8. HashMap实现原理(jdk1.7),源码分析
  9. 【每日Scrum】第三天冲刺
  10. 吴裕雄--天生自然MySQL学习笔记:MySQL 导入数据