uoj#218. 【UNR #1】火车管理

题目描述

uoj#218. 【UNR #1】火车管理
n,m<=5e5,x<=1e3

题解

想了一下就想出了log^2的,之后刚了一个下午尝试去掉一个log结果发现把set改成优先队列就过了

log^2的自然做法:

在线段树上挂加进去的数,如果下传的话时间会假,因此不下传标记

弹栈就单点查询,把经过的所有区间内时间最大的弹掉,第二大的就是新的值

弹掉之后下传,注意只需要下传一个标记,往下一共有log个区间

时间是log^2的,用优先队列即可通过并且不是最慢

题解一个log的自然做法:

主席树直接维护每个时刻的栈顶(时间/值),弹栈等于把某个位置修改为某个时间该位置的值,直接查询即可

简单自然

code

log^2

#include <bits/stdc++.h>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define min(a,b) (a<b?a:b)
#define max(a,b) (a>b?a:b)
#define ll long long
//#define file
using namespace std;

int n,m,tp,Tp,i,j,k,l,x,y,z,ans,T,Find;
char st[21],ch;
struct type{int x,t;} Find2;
bool operator < (type a,type b) {return a.t<b.t;}
struct tree1{
	int tr[2000001],Tr[2000001];
	void down(int t,int len)
	{
		if (Tr[t]>-1)
		{
			if (len>1) Tr[t*2]=Tr[t*2+1]=Tr[t];
			tr[t]=Tr[t]*len;Tr[t]=-1;
		}
	}
	void change(int t,int l,int r,int x,int y,int s)
	{
		int mid=(l+r)/2;
		down(t,r-l+1);
		if (x<=l && r<=y)
		{
			Tr[t]=s,down(t,r-l+1);
			return;
		}
		down(t*2,mid-l+1),down(t*2+1,r-mid);
		
		if (x<=mid) change(t*2,l,mid,x,y,s);
		if (mid<y) change(t*2+1,mid+1,r,x,y,s);
		tr[t]=tr[t*2]+tr[t*2+1];
	}
	int find(int t,int l,int r,int x,int y)
	{
		int mid=(l+r)/2,ans=0;
		down(t,r-l+1);
		if (x<=l && r<=y) return tr[t];
		
		if (x<=mid) ans+=find(t*2,l,mid,x,y);
		if (mid<y) ans+=find(t*2+1,mid+1,r,x,y);
		return ans;
	}
} t1;
struct tree2{
	priority_queue<type> tr[2000001];
	void change(int t,int l,int r,int x,int y,type s)
	{
		int mid=(l+r)/2;
		if (x<=l && r<=y) {tr[t].push(s);return;}
		
		if (x<=mid) change(t*2,l,mid,x,y,s);
		if (mid<y) change(t*2+1,mid+1,r,x,y,s);
	}
	void find(int t,int l,int r,int x)
	{
		int mid=(l+r)/2;
		type s;
		
		if (!tr[t].empty())
		{
			s=tr[t].top();
			if (s.t>Find2.t) Find=t,Find2=s;
		}
		if (l==r) return;
		
		if (x<=mid) find(t*2,l,mid,x);
		else find(t*2+1,mid+1,r,x);
	}
	void Change(int t,int l,int r,int x,type s)
	{
		int mid=(l+r)/2;
		if (l==r) return;
		
		if (x<=mid)
		{
			if (t>=Find) tr[t*2+1].push(s);
			Change(t*2,l,mid,x,s);
		}
		else
		{
			if (t>=Find) tr[t*2].push(s);
			Change(t*2+1,mid+1,r,x,s);
		}
	}
} t2;

void Read(int &x) {x=0; ch=getchar(); while (ch<'0' || ch>'9') ch=getchar(); while (ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();}
void Write(int x) {int i=0; if (!x) {putchar('0');putchar('\n');return;} while (x) st[++i]=x%10+'0',x/=10; while (i) putchar(st[i--]);putchar('\n');}

int main()
{
	#ifdef file
	freopen("uoj218.in","r",stdin);
	freopen("uoj218.out","w",stdout);
	#endif
	
	memset(t1.Tr,255,sizeof(t1.Tr));
	
	Read(n),Read(m),Read(tp);
	fo(T,1,m)
	{
		Read(Tp);
		switch (Tp)
		{
			case 1:{
				Read(j);Read(k);j=(j+ans*tp)%n+1;k=(k+ans*tp)%n+1;
				x=min(j,k),y=max(j,k);
				ans=t1.find(1,1,n,x,y);
				Write(ans);
				break;
			}
			case 2:{
				Read(x);x=(x+ans*tp)%n+1;Find=0;Find2.t=-1;
				t2.find(1,1,n,x);
				if (Find)
				{
					t2.tr[Find].pop();
					t2.Change(1,1,n,x,Find2);
					
					Find=0;Find2={0,-1};
					t2.find(1,1,n,x);
					t1.change(1,1,n,x,x,Find2.x);
				}                      
				break;
			}
			case 3:{
				Read(j),Read(k),Read(z);j=(j+ans*tp)%n+1;k=(k+ans*tp)%n+1;
				x=min(j,k),y=max(j,k);
				t1.change(1,1,n,x,y,z);
				t2.change(1,1,n,x,y,{z,T});
				break;
			}
		}
	}
	
	fclose(stdin);
	fclose(stdout);
	return 0;
}
上一篇:[解题报告]【UNR #4】校园闲逛


下一篇:Map 使用踩坑记录