WA 求助
查看原帖
WA 求助
490484
include13_fAKe楼主2024/11/3 16:48
#include<bits/stdc++.h>
#define int long long
#define n ((1<<n_)-1)
#define mp(a,b) make_pair(a,b)
using namespace std;

const int N_=20;	//点的层数 
const int N=6e5;	//点的总数 
const int mod=998244353;
vector<pair<int,int> > g0[N];	//原来的图 
vector<pair<int,int> > g1[N];	//反向的图  
int n_;
int m;
vector<int> g2[N];	//第二类边 
struct edge_2{
	//表示第二类边 
	int u,v,w;
}edge2[N];
int edge_num[N];	//dfs 到每一个点时的第二类边的条数 

int ptr;	//
int h1[N];	//h 的辅助数组 
vector<int> h[N_];	//第二类边的临时使用 
int include13;
vector<int> h_;	//目前的情况  

int g0_zdl[N];	//原图最短路  
int g1_zdl[N];	//反图最短路 
bool g0_[N],g1_[N];
int now1[N];	//记录目前能不能跑  
inline int read(){
	int num=0;
	int f=1;
	char c=getchar();
	while(!isdigit(c)){
		if(c=='-')	f=-1;
		c=getchar();
	}
	while(isdigit(c)){
		num=(num<<1)+(num<<3)+(c-'0');
		c=getchar();
	}
	return num*f;
}
inline void dfs0(int u,int u0){
	if(u>n)	return;
	g0_zdl[u]=1e18;
	g1_zdl[u]=1e18;
	g0_[u]=g1_[u]=false;
	now1[u]=u0;
	dfs0(u*2,u0),dfs0(u*2+1,u0);
	return;
}
inline void init(int u){
	//init 分为两个部分 第一部分处理 u 的孩子 第二部分处理 u 的祖先  
	dfs0(u,u);
	int u0=u;
	while(u0){
		now1[u0]=u;
		g0_zdl[u0]=1e18,g1_zdl[u0]=1e18;
		u0>>=1;
	}
	g0_zdl[u]=g1_zdl[u]=0;
	return;
} 
inline int dfs_g0_1(int u){
	//计算有效点数 
	if(u>n)	return 0;
	return (dfs_g0_1(u*2)+dfs_g0_1(u*2+1)+(g0_zdl[u]!=1e18))%mod; 
}
inline int dfs_g1_1(int u){
	//计算有效点数 
	if(u>n)	return 0;
	return (dfs_g1_1(u*2)+dfs_g1_1(u*2+1)+(g1_zdl[u]!=1e18))%mod; 
}
inline int dfs_g0_2(int u){
	//计算有效最短路径数 
	if(u>n)	return 0;
	return (dfs_g0_2(u*2)+dfs_g0_2(u*2+1)+((g0_zdl[u]!=1e18)?g0_zdl[u]:0))%mod; 
}
inline int dfs_g1_2(int u){
	//计算有效最短路径数 
	if(u>n)	return 0;
	return (dfs_g1_2(u*2)+dfs_g1_2(u*2+1)+((g1_zdl[u]!=1e18)?g1_zdl[u]:0))%mod; 
}
inline void dijkstra(int u){
	init(u); 
	priority_queue<pair<int,int> > q;//第一个存负的点权 第二个存点号  跑一次正图 一次反图  
	q.push(mp(0,u));
	while(!q.empty()){
		int now_u=q.top().second;
		int now_zdl=-q.top().first;
		q.pop();
		if(g0_[now_u])	continue;
		g0_[now_u]=true;
		for(register int i=0;i<g0[now_u].size();i++){
			int v=g0[now_u][i].first;
			int w=g0[now_u][i].second;
			if(g0_zdl[v]>now_zdl+w){
				g0_zdl[v]=now_zdl+w;
				q.push(mp(-w,v));
			}
		} 
	}
	q.push(mp(0,u));
	while(!q.empty()){
		int now_u=q.top().second;
		int now_zdl=-q.top().first;
		q.pop();
		if(g1_[now_u])	continue;
		g1_[now_u]=true;
		for(register int i=0;i<g1[now_u].size();i++){
			int v=g1[now_u][i].first;
			int w=g1[now_u][i].second;
			if(g1_zdl[v]>now_zdl+w){
				g1_zdl[v]=now_zdl+w;
				q.push(mp(-w,v));
			}
		} 
	}
	//计算八个值:原图/反图 左子树/右子树 点数/最短路长度之和 
	int g0_l_1=dfs_g0_1(u*2)+1;//左子树上的有效点数 
	int g0_r_1=dfs_g0_1(u*2+1)+1;//右子树上的有效点数 
	int g0_l_2=dfs_g0_2(u*2);	//左子树上的有效最短路长度  
	int g0_r_2=dfs_g0_2(u*2+1);
	int g1_l_1=dfs_g1_1(u*2)+1;//左子树上的有效点数 
	int g1_r_1=dfs_g1_1(u*2+1)+1;//右子树上的有效点数 
	int g1_l_2=dfs_g1_2(u*2);	//左子树上的有效最短路长度  
	int g1_r_2=dfs_g1_2(u*2+1);
	include13+=g0_l_1*g1_r_2;
//	cout<<include13<<endl;
	include13+=g0_r_1*g1_l_2;
//	cout<<include13<<endl;
	include13+=g0_l_2*g1_r_1;
//	cout<<include13<<endl;
	include13+=g0_r_2*g1_l_1;
	include13%=mod;
//	cout<<include13<<endl;
//	cout<<endl;
	return;
}
inline void dfs(int u){
	if(u>n)	return;
	dfs(u*2),dfs(u*2+1);
//	cout<<'#'<<' '<<u<<endl;
	if(h1[ptr]==u*2+1&&h1[ptr-1]==u*2){
		for(int i=1;i<=2;i++){
//			cout<<'&'<<endl;
			for(int j=0;j<h[ptr].size();j++){
				int now=h[ptr][j];
				h_.push_back(now);
			}
			while(h[ptr].size())	h[ptr].pop_back();
			h1[ptr]=0;
			ptr--;
		} 
//		ptr-=2;
	}
	for(int i=0;i<g2[u].size();i++){
		int now=g2[u][i];
		h_.push_back(now);
	}
	h[++ptr]=h_;
	h1[ptr]=u;
	edge_num[u]=h[ptr].size();
//	cout<<"第 "<<u<<"个"<<endl; 
//	cout<<u<<' '<<edge_num[u]<<' '<<ptr<<endl;
	for(int i=0;i<edge_num[u];i++){
		int u1=edge2[h_[i]].u,v1=edge2[h_[i]].v,w1=edge2[h_[i]].w;
		g0[u1].push_back(mp(v1,w1)),g1[v1].push_back(mp(u1,w1)); 
//		cout<<"& "<<u1<<' '<<v1<<endl;
	}
	dijkstra(u); 
//	cout<<endl;
//	cout<<h[ptr].size()<<' '<<ptr<<endl;
//	cout<<endl; 
//	for(int i=1;i<=n;i++){
//		cout<<g0[i].size()<<' '<<g1[i].size()<<endl;
//	}
//	cout<<endl;
	for(int i=0;i<edge_num[u];i++){
		int u1=edge2[h_[i]].u,v1=edge2[h_[i]].v;
		g0[u1].pop_back(),g1[v1].pop_back();
	}
	while(h_.size())	h_.pop_back();
	return;
}
signed main(){
//	freopen("trade.in","r",stdin);
//	freopen("trade.out","w",stdout); 
	memset(now1,0x3f,sizeof(now1));
	cin>>n_>>m;
	for(int i=2;i<=n;i++){
		int u=i,v=i/2,w;
		w=read();
		g0[u].push_back(mp(v,w)),g1[v].push_back(mp(u,w));
	}	//O(2^n)
	for(int i=1;i<=m;i++){
		int u,v,w;
		u=read(),v=read(),w=read();
		g2[v].push_back(i);
		edge2[i]=(edge_2){u,v,w};
	}	//O(m)
//	for(int i=1;i<=n;i++){
//		cout<<g2[i].size()<<' ';
//	}
//	cout<<endl;
	dfs(1);
	cout<<include13<<endl;
	return 0;
} 
//我知道你我都没有错 只是忘了怎么退后  
2024/11/3 16:48
加载中...