2024/8/16

Redamancy_Lydic發表於2024-08-16

P1533 可憐的狗狗

裸的主席樹,但是我想到一種其它的做法。

用莫隊加上平衡樹,原因為題目保證 \(a_i\) 互不相同,算了一下複雜度勉強能過。

平衡樹的話可以使用 pbds 內建的那顆。

跑得飛快,碾壓主席樹。

點選檢視程式碼
#include<bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define int long long
using namespace std;
using namespace  __gnu_pbds;
tree<int,null_type,less<int>,rb_tree_tag,tree_order_statistics_node_update> tr;//從小到大
int findnum(int k){auto it=tr.find_by_order(k-1);return ((it!=tr.end())?(*it):1e9+7);}//查元素
// int findrank(int x){return tr.order_of_key(x)+1;}//查排名
inline int read()
{
	int w=1,s=0;char ch=getchar();
	while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();}
	while(isdigit(ch)){s=s*10+(ch-'0');ch=getchar();}
	return w*s;
}
const int mod=1e9+7;
const int maxn=1e6+10;
const int inf=1e17;
const double eps=1e-10;
int n,m;
int a[maxn];
int id[maxn],len;
struct no
{
	int l,r,k,pos;
	inline friend bool operator < (no q,no w) 
	{
		if(id[q.l]==id[w.l])
		{
			if(id[q.l]&1) return q.r<w.r;
			else return q.r>w.r;
		}
		else
		{
			return q.l<w.l;
		}
	}
}q[maxn];
int ans[maxn];
signed main()
{
#ifdef Lydic
    freopen(".in","r",stdin);
    freopen(".out","w",stdout);
#endif
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	{
		a[i]=read();
	}
	for(int i=1;i<=m;i++)
	{
		q[i]={read(),read(),read(),i};
	}
	len=sqrt(n*1.0);
	for(int i=1;i<=n;i++)id[i]=(i-1)/len+1;
	sort(q+1,q+m+1);
	int l=0,r=0;
	for(int i=1;i<=m;i++)
	{
		while(r<q[i].r)
		{
			r++;
			tr.insert(a[r]);
		}
		while(r>q[i].r)
		{
			tr.erase(a[r]);
			r--;
		}
		while(l<q[i].l)
		{
			tr.erase(a[l]);
			l++;
		}
		while(l>q[i].l)
		{
			l--;
            tr.insert(a[l]);
		}
		int res=findnum(q[i].k);
		ans[q[i].pos]=res;
	}
	for(int i=1;i<=m;i++)
	printf("%lld\n",ans[i]);
	return 0;
}

P1668 [USACO04DEC] Cleaning Shifts S

典型線段樹最佳化DP,設 \(dp_i\) 表示區間 \([1,i]\) 所需最小線段數量。初始化所有 \(l=1\) 的線段都有 \(dp_r=1\)

然後按照 \(r\) 排序,對於當前的 \(r\),轉移的時候顯然 \(dp_r=dp_j+1~~ (l-1\le j \le r)\)

然後一個線段樹搞一下就結束了。

點選檢視程式碼
#include<bits/stdc++.h>
// #include <ext/pb_ds/assoc_container.hpp>
// #include <ext/pb_ds/tree_policy.hpp>
#define int long long
using namespace std;
// using namespace  __gnu_pbds;
// tree<int,null_type,less<int>,rb_tree_tag,tree_order_statistics_node_update> tr;//從小到大
// int findnum(int k){auto it=tr.find_by_order(k-1);return ((it!=tr.end())?(*it):1e9+7);}//查元素
// int findrank(int x){return tr.order_of_key(x)+1;}//查排名
inline int read()
{
	int w=1,s=0;char ch=getchar();
	while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();}
	while(isdigit(ch)){s=s*10+(ch-'0');ch=getchar();}
	return w*s;
}
const int mod=1e9+7;
const int maxn=1e6+10;
const int inf=1e17;
const double eps=1e-10;
int n,T;
struct no
{
	int l,r;
	inline friend bool operator < (no x,no y)
	{
		return x.r<y.r||x.r==y.r&&x.l<y.l;
	}
}a[maxn];
struct Seg
{
	int l,r,d;
}t[maxn<<2];
void build(int p,int l,int r)
{
	t[p].l=l,t[p].r=r;
	if(l==r)
	{
		t[p].d=1e9+7;
		return ;
	}
	int mid=(l+r)>>1;
	build(p<<1,l,mid);
    build(p<<1|1,mid+1,r);
	t[p].d=min(t[p*2].d,t[p*2+1].d);
}
void upd(int p)
{
	t[p].d=min(t[p*2].d,t[p*2+1].d);
}
void change(int p,int x,int k)
{
	if(t[p].l==t[p].r)
	{
		t[p].d=min(t[p].d,k);
		return ;
	}
	int mid=(t[p].l+t[p].r)>>1;
	if(x<=mid)change(p<<1,x,k);
    else change(p<<1|1,x,k);
    upd(p);
}
int ask(int p,int l,int r)
{
	if(t[p].l>=l&&t[p].r<=r)
	{
		return t[p].d;
	}
	int mid=(t[p].l+t[p].r)/2,re=1e9+7;
	if(mid>=l)re=min(re,ask(p*2,l,r));
	if(mid<r)re=min(re,ask(p*2+1,l,r));
    return re; 
}
signed main()
{
#ifdef Lydic
    freopen(".in","r",stdin);
    freopen(".out","w",stdout);
#endif
	cin>>n>>T;
	for(int i=1;i<=n;i++)
	{
		a[i].l=read(),a[i].r=read();
	}
	build(1,1,T);
	sort(a+1,a+n+1);
	for(int i=1;i<=n;i++)if(a[i].l==1)change(1,a[i].r,1);
	for(int i=1;i<=n;i++)
	{
		int mii=ask(1,a[i].r,a[i].r);
		mii=min(mii,ask(1,a[i].l-1,a[i].r-1)+1);
		change(1,a[i].r,mii);
	}
	int ans=ask(1,T,T);
	cout<<(ans>1e9?-1:ans);
	return 0;
}

P6348 [PA2011] Journeys

線段樹最佳化建圖板子。

需要注意的是,一不小心就會RE,所以稍微改一下建圖方式每次開一個虛擬點進行連邊即可。

空間快爆掉。

點選檢視程式碼
#include<bits/stdc++.h>
// #include <ext/pb_ds/assoc_container.hpp>
// #include <ext/pb_ds/tree_policy.hpp>
#define int long long
using namespace std;
// using namespace  __gnu_pbds;
// tree<int,null_type,less<int>,rb_tree_tag,tree_order_statistics_node_update> tr;//從小到大
// int findnum(int k){auto it=tr.find_by_order(k-1);return ((it!=tr.end())?(*it):1e9+7);}//查元素
// int findrank(int x){return tr.order_of_key(x)+1;}//查排名
inline int read()
{
	int w=1,s=0;char ch=getchar();
	while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();}
	while(isdigit(ch)){s=s*10+(ch-'0');ch=getchar();}
	return w*s;
}
const int mod=1e9+7;
const int maxn=1e6+10;
const int inf=1e17;
const double eps=1e-10;
int n,m,s,k;
struct Seg
{
	int l,r;
}t[5000100];
struct no
{
	int y,v;
};
vector<no> G[maxn];
void add(int x,int y,int v)
{
	G[x].push_back({y,v});
}
int id[maxn];
void build(int p,int l,int r)
{
	t[p].l=l,t[p].r=r;
	if(l==r)
	{
		id[l]=p;
		return ;
	}
	int mid=(l+r)>>1;
	add(p,p*2,0);add(p,p*2+1,0);
	add(p*2+k,p+k,0);add(p*2+1+k,p+k,0);
	build(p*2,l,mid);
	build(p*2+1,mid+1,r);
}
vector<int> vv;
void change(int p,int l1,int r1)
{
	if(t[p].l>=l1&&t[p].r<=r1)
	{
		vv.push_back(p);
		return ;
	}
	int mid=(t[p].l+t[p].r)>>1;
	if(l1<=mid)change(p*2,l1,r1);
	if(mid<r1)change(p*2+1,l1,r1);
}
void change2(int p,int l1,int r1)
{
	if(t[p].l>=l1&&t[p].r<=r1)
	{
		for(auto i : vv)
		{
			add(i+k,p,1);
			add(p+k,i,1);
		}
		return ;
	}
	int mid=(t[p].l+t[p].r)>>1;
	if(l1<=mid)change2(p*2,l1,r1);
	if(mid<r1)change2(p*2+1,l1,r1);
}
struct dii
{
	int y,id;
	inline friend bool operator < (dii x,dii y)
	{
		return x.y>y.y;
	}
};
int dis[maxn];
bool vis[maxn];
void distla(int s)
{
	memset(dis,0x3f,sizeof dis);
	priority_queue<dii> q;
	dis[s]=0;
	q.push({0,s});
	while(!q.empty())
	{
		int u=q.top().id;
		q.pop();
		if(vis[u])continue;
		vis[u]=1;
		for(auto i : G[u])
		{
			int y=i.y,v=i.v;
			if(dis[u]+v<dis[y])
			{
				dis[y]=dis[u]+v;
				if(!vis[y])
				q.push({dis[y],y});
			}
		}
	}
}
signed main()
{
#ifdef Lydic
    freopen(".in","r",stdin);
    freopen(".out","w",stdout);
#endif
	cin>>n>>m>>s;
	k=5e5+1;
	build(1,1,n);
	for(int i=1;i<=n;i++)
	{
		add(id[i],id[i]+k,0);
		add(id[i]+k,id[i],0);
	}
	for(int i=1;i<=m;i++)
	{
		int l1=read(),r1=read(),l2=read(),r2=read();
		vv.clear();
		change(1,l1,r1);
		change2(1,l2,r2);
	}
	distla(id[s]+k);
	for(int i=1;i<=n;i++)
	cout<<(dis[id[i]]==0x3f3f3f3f3f3f3f3fll?-1:dis[id[i]])<<endl;
	return 0;
}