icpc网络赛 J Red-Black Paths离线,前缀异或,重构图,暴力剪枝

Posted goto_1600

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了icpc网络赛 J Red-Black Paths离线,前缀异或,重构图,暴力剪枝相关的知识,希望对你有一定的参考价值。

Link
题意:
给定一个图,按照时间顺序建图,给点染成红黑色,求相邻两次询问之间新增的红黑路的价值的异或和,红黑路的价值指的是路上每个点的权值乘以长度。数据保证所有红黑路长度<=10。保证所有红黑路<=5000000
思路:
由于可以离线,我们可以按照时间序来存储图,由于我们只要红开头,黑结尾的,对于其他的我们可以减枝,把无关紧要的点去掉,一看复杂度, ∑ 红 黑 路 < = 5000000 \\sum红黑路<=5000000 <=5000000,就算每次暴力搜索红黑路也只有 O ( 10 ) O(10) O(10) 5e7的复杂度绰绰有余,启发我们构造新图,只对有用的点连边,然后用时间序来保证答案的正确性,维护个前缀异或的答案,当我们询问两个询问之间的操作,也就是区间异或值查询,不再赘述。
代码:

//#pragma GCC target("avx")
//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
//#pragma GCC optimize("Ofast")
// created by myq
#include<iostream>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<climits>
#include<cmath>
#include<cctype>
#include<stack>
#include<queue>
#include<list>
#include<vector>
#include<set>
#include<map>
#include<sstream>
#include<unordered_map>
#include<unordered_set>
using namespace std;
typedef long long ll;
#define x first
#define y second
typedef pair<int,int> pii;
const int N = 400010,M=1000010;
const int mod=998244353;
inline int read()
{
	int res=0;
	int f=1;
	char c=getchar();
	while(c>'9' ||c<'0')
	{
		if(c=='-')	f=-1;
		c=getchar();
	}
	while(c>='0'&&c<='9')
	{
		res=(res<<3)+(res<<1)+c-'0';
	}
	return res;
 }
int h[N],e[M],ne[M],w[M],idx;
bool flag[N];
int red[N];
int black[N];
ll ans[N];
bool vis[N];
vector<int>q;
void add(int a,int b,int c){
	e[idx]=b,ne[idx]=h[a],w[idx]=c,h[a]=idx++;
}
void dfs(int x){
	if(black[x])
	flag[x]=true;
	vis[x]=true;
	for(int i=h[x];~i;i=ne[i]){
		int j=e[i];
		if(vis[j]){
			flag[x]|=flag[j];
			continue;
		}
		dfs(j);
		flag[x]|=flag[j];
	}
}
struct node{
	int a;
	int b;
	int c;
}edge[M];
int cnt;
void rebuild(){
	idx=0;
	memset(h,-1,sizeof h);
	for(int i=0;i<cnt;i++){
		int a=edge[i].a;
		int b=edge[i].b;
		int w=edge[i].c;
//		cout<<a<<" "<<b<<endl;
		if(flag[a]&flag[b])
		add(a,b,w);
	}
}
void dfss(int u,int tm,ll sum,int dep){
	if(black[u])
	{
		ans[max(tm,black[u])]^=sum;
	}
	for(int i=h[u];~i;i=ne[i]){
		int j=e[i];
		dfss(j,max(tm,w[i]),sum+1ll*dep*j,dep+1);
	}
	
}
vector<int>Red;
signed main()
{
	 ios::sync_with_stdio(0);
	 cin.tie(0);
	 cout.tie(0);
	memset(h,-1,sizeof h);
	int n;
	cin>>n;
	 cnt=0;
	for(int i=1;i<=n;i++){
		int op;
		cin>>op;
		if(op==1){
			int u,v,w;
			cin>>u>>v;
			w=i;
			edge[cnt++]={u,v,w};	
			add(u,v,w);
		}
		else if(op==2){
			int x;
			cin>>x;
			red[x]=i;
			Red.push_back(x);
		}
		else if(op==3){
			int x;
			cin>>x;
			black[x]=i;
		}
		else
		{
			q.push_back(i);	
		}
	}
	for(auto x:Red)
		if(!vis[x])
		dfs(x);
	rebuild();
	for(auto x:Red)
		dfss(x,red[x],1ll*x,2);
	for(int i=1;i<=n;i++)	ans[i]^=ans[i-1];
	for(int i=0;i<q.size();i++){
//		cout<<q[i]<<"qwq"<<endl;
		int res=ans[q[i]];
		if(i)
		res^=ans[q[i-1]];
		cout<<res<<endl;
	}
	return 0;

}
/**
* In every life we have some trouble
* When you worry you make it double
* Don't worry,be happy.
**/



以上是关于icpc网络赛 J Red-Black Paths离线,前缀异或,重构图,暴力剪枝的主要内容,如果未能解决你的问题,请参考以下文章

icpc网络赛 J Red-Black Paths离线,前缀异或,重构图,暴力剪枝

icpc网络赛第二场K Meal

icpc网络赛第二场K Meal

ICPC 2018 南京网络赛 J Magical Girl Haze(多层图最短路)

2018ICPC南京赛区网络赛J Sum(素数筛+找规律)

2018icpc南京网络赛-L Magical Girl Haze (分层图最短路)