记录编号 245614 评测结果 AAAAAAAAAAAAAAAAAAAA
题目名称 [国家集训队 2011] Crash的旅行计划 最终得分 100
用户昵称 Gravatarmikumikumi 是否通过 通过
代码语言 C++ 运行时间 16.209 s
提交时间 2016-04-03 21:16:21 内存使用 14.81 MiB
显示代码纯文本
#include<cstdio>
#include<iostream>
#include<vector>
#include<set>
using namespace std;
const int SIZEN=100010,INF=0x7fffffff/300;
int N;
int W[SIZEN];
vector<int> s[SIZEN];
void add(int fr,int to)
{
	s[fr].push_back(to);
	s[to].push_back(fr);
}
int fa[SIZEN]={0},pos[SIZEN],son[SIZEN],top[SIZEN],en[SIZEN];
int dep[SIZEN],siz[SIZEN];
set<pair<int,int>,greater<pair<int,int> > > down[SIZEN];
int totw=0;
void print_down(int i)
{
	cout<<"i:"<<i<<endl;
	set<pair<int,int>,greater<pair<int,int> > >::iterator it;
	for(it=down[i].begin();it!=down[i].end();it++)
	{
		pair<int,int> a=*it;
		cout<<a.first<<" "<<a.second<<endl;
	}
}
void dfs(int x)
{
	son[x]=0;dep[x]=dep[fa[x]]+1;
	siz[x]=1;
	for(int i=0;i<s[x].size();i++)
	{
		int v=s[x][i];
		if(v==fa[x]) continue;
		fa[v]=x;
		dfs(v);
		siz[x]+=siz[v];
		if(siz[v]>siz[son[x]]) son[x]=v;
	}
}
void make_tree(int x,int tp)
{
	pos[x]=++totw;top[x]=tp;
	if(son[x]) make_tree(son[x],tp),en[x]=en[son[x]];
	if(!son[x]) en[x]=x;
	for(int i=0;i<s[x].size();i++)
	{
		int v=s[x][i];
		if(v==fa[x]||v==son[x]) continue;
		make_tree(v,v);
	}
}
class miku//线段树
{
public:
	int l,r;
	int maxl,maxr,sum;
}tr[SIZEN*4];
int PW[SIZEN]={0};
void built(int root,int l,int r)
{
	tr[root].sum=0;
	tr[root].maxl=tr[root].maxr=-INF;
	tr[root].l=l;tr[root].r=r;
	if(l==r) return;
	int mid=(l+r)/2;
	built(root*2,l,mid);built(root*2+1,mid+1,r);
}
void push(int root,int k,int be,int w,int fr)
{
	set<pair<int,int>,greater<pair<int,int> > >::iterator it;
	it=down[k].lower_bound(make_pair(be,fr));
	if(it!=down[k].end()) down[k].erase(it);
	down[k].insert(make_pair(w,fr));
	it=down[k].begin();
	pair<int,int> a=*it;
	if(pos[a.second]==k) it++;
	if(it!=down[k].end())
	{
		a=*it;
	    tr[root].maxl=tr[root].maxr=max(PW[k],a.first+PW[k]);
	}
	else tr[root].maxl=tr[root].maxr=PW[k];
	tr[root].sum=PW[k];
}
void update(int root)
{
	tr[root].maxl=max(tr[root*2].maxl,tr[root*2].sum+tr[root*2+1].maxl);
	tr[root].maxr=max(tr[root*2+1].maxr,tr[root*2].maxr+tr[root*2+1].sum);
	tr[root].sum=tr[root*2].sum+tr[root*2+1].sum;
}
void add_seg(int root,int k,int w,int be,int fr)
{
	if(tr[root].r<k||tr[root].l>k) return;
	if(tr[root].l==tr[root].r)
	{
		push(root,k,be,w,fr);
		return;
	}
	add_seg(root*2,k,w,be,fr);add_seg(root*2+1,k,w,be,fr);
	update(root);
}
miku get(int root,int l,int r)
{
	miku re;
	re.maxl=re.maxr=-INF;re.sum=0;
	if(tr[root].r<l||tr[root].l>r) return re;
	if(l<=tr[root].l&&tr[root].r<=r) return tr[root];
	miku tem1=get(root*2,l,r),tem2=get(root*2+1,l,r);
	re.maxl=max(tem1.maxl,tem1.sum+tem2.maxl);
	re.maxr=max(tem2.maxr,tem2.sum+tem1.maxr);
	re.sum=tem1.sum+tem2.sum;
	return re;
}
void add_tr(int k,int w,int be)//对整棵树的down和链的修改
{
	int tmp=w,v=k,fr=v;
	PW[pos[k]]=w;
	while(v!=0)
	{
		miku tem1=get(1,pos[top[v]],pos[en[v]]);
		add_seg(1,pos[v],tmp,be,fr);
		miku tem2=get(1,pos[top[v]],pos[en[v]]);
		fr=top[v];v=fa[top[v]];
		tmp=tem2.maxl;be=tem1.maxl;
	}
}
void prepare()
{
	dfs(1);
	make_tree(1,1);
	built(1,1,totw);
	for(int i=1;i<=N;i++) PW[pos[i]]=W[i];
	for(int i=1;i<=N;i++) add_tr(i,W[i],-INF);
}
int query(int x)
{
	set<pair<int,int>,greater<pair<int,int> > >::iterator it;
	int v=x;
	int ans=W[x];
	miku tem1;
	int sum=0;
	int be=v;
	while(v!=0)
	{
		it=down[pos[v]].begin();
		pair<int,int> a=*it;
		if(a.second==be) it++;
		if(it!=down[pos[v]].end())
		{
			a=*it;
			if(a.second==v)
			ans=max(ans,a.first+sum);
			else ans=max(ans,a.first+sum+W[v]);
		}
		if(v!=en[v])
		{
			tem1=get(1,pos[v]+1,pos[en[v]]);
			ans=max(ans,tem1.maxl+W[v]+sum);
		}
		if(v!=top[v])
		{
			tem1=get(1,pos[top[v]],pos[v]-1);
			ans=max(ans,tem1.maxr+W[v]+sum);
			sum+=tem1.sum;
		}
		sum+=W[v];
		be=top[v];v=fa[top[v]];
	}
	return ans;
}
int main()
{
	freopen("nt2011_travel_jzp.in","r",stdin);
	freopen("nt2011_travel_jzp.out","w",stdout);
	char C;
	int now,A,B,Q,M,L,tmp;
	scanf("%c",&C);
	scanf("%d%d%d",&N,&M,&L);
	scanf("%d%d%d%d",&now,&A,&B,&Q);
	for(int i=1;i<=N;i++)
	{
		now=(now*A+B)%Q;tmp=now%10000;
		now=(now*A+B)%Q;
		if(now*2<Q) tmp*=-1;
		W[i]=tmp;
	}
	for(int i=1;i<N;i++)
	{
		now=(now*A+B)%Q;
		tmp=(i<L)?i:L;
		add(i-now%tmp,i+1);
	}
	prepare();
	for(int i=1;i<M;i++)
	{
		now=(now*A+B)%Q;
		if(now*3<Q)
		{
			now=(now*A+B)%Q;
			int ans=query(now%N+1);
			printf("%d\n",ans);
		}
		else
		{
			now=(now*A+B)%Q,tmp=now%10000;
			now=(now*A+B)%Q;
			if(now*2<Q) tmp*=-1;
			now=(now*A+B)%Q;
			add_tr(now%N+1,tmp,W[now%N+1]);
			W[now%N+1]=tmp;
		}
	}
	return 0;
}