【坑坑坑】数据结构 Contest



B

矩形面积k次覆盖并

代码写得很不熟练


#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
#define rep(i,l,r) for(int i=(l),_=(r);i<=_;i++)
#define per(i,r,l) for(int i=(r),_=(l);i>=_;i--)
#define MS(arr,x) memset(arr,x,sizeof(arr))
#define INE(i,u) for(int i=head[u];~i;i=e[i].next)
#define LL long long
inline const int read()
{int r=0,k=1;char c=getchar();for(;c<'0'||c>'9';c=getchar())if(c=='-')k=-1;
for(;c>='0'&&c<='9';c=getchar())r=r*10+c-'0';return k*r;}

const int N=30003;
int n,k;
struct Line{
	int x,y1,y2,flag;
}l[N*2];
int y[N*2],tot,t;
int sum[N*8][12],cover[N*8];

bool cmp(const Line &A,const Line &B){return A.x<B.x;}
void up(int o,int L,int R)
{
	rep(i,0,k) sum[o][i]=0;
	/*if(cover[o]>=k)
	{
		sum[o][k]=y[R+1]-y[L];
	}
	else if(L!=R)
	{
		rep(i,cover[o],k-1) sum[o][i]=sum[o<<1][i-cover[o]]+sum[o<<1|1][i-cover[o]];
		rep(i,k-cover[o],k) sum[o][k]+=sum[o<<1][i]+sum[o<<1|1][i];
	}
	else
	{
		sum[o][cover[o]]=y[R+1]-y[L];
	}*/
	rep(i,0,k)
	{
		if(cover[o]>=i)
		{
			sum[o][i]=y[R+1]-y[L];
		}
		else if(L!=R)
		{
			sum[o][i]=sum[o<<1][i-cover[o]]+sum[o<<1|1][i-cover[o]];
		}
		else
		{
			sum[o][i]=0;
		}
	}
}
#define LS o<<1,L,mid
#define RS o<<1|1,mid+1,R
void modify(int l,int r,int x,int o=1,int L=1,int R=t-1)
{
	if(l<=L && R<=r)
	{
		cover[o]+=x;
		up(o,L,R);
		return;
	}
	int mid=L+R>>1;
	if(r<=mid) modify(l,r,x,LS);
	else if(l>mid) modify(l,r,x,RS);
	else modify(l,mid,x,LS), modify(mid+1,r,x,RS);
	up(o,L,R);
}

void input()
{
	tot=0;
    n=read(); k=read();
    rep(i,1,n)
    {
    	int x1=read(),y1=read(),x2=read(),y2=read(); x2++; y2++;
    	l[++tot].x=x1; l[tot].y1=y1; l[tot].y2=y2; l[tot].flag=1;  y[tot]=y1;
    	l[++tot].x=x2; l[tot].y1=y1; l[tot].y2=y2; l[tot].flag=-1; y[tot]=y2;
    }
    sort(&l[1],&l[tot+1],cmp);
    sort(&y[1],&y[tot+1]);
    t=unique(&y[1],&y[tot+1])-&y[1];
}
void solve()
{
	LL ans=0;
	rep(i,1,tot)
	{
		int L=lower_bound(&y[1],&y[t+1],l[i].y1) - &y[1] + 1;
		int R=lower_bound(&y[1],&y[t+1],l[i].y2) - &y[1] + 1;
		if(i>1) ans+=(LL)(l[i].x-l[i-1].x)*sum[1][k];
		modify(L,R-1,l[i].flag);
	}
	cout<<ans<<endl;
}

int main()
{
    int t=read();
    for(int T=1;T<=t;T++)printf("Case %d: ",T),
    input(),solve();
    return 0;
}

E

还不会分块的做法


H

很神的题啊

点分治+DP

代码实现得很麻烦,我写得最长

#pragma comment(linker, "/STACK:102400000,102400000")
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <cmath>
#include <algorithm>
#include <vector>
#include <set>
using namespace std;
#define rep(i,l,r) for(int i=(l),_=(r);i<=_;i++)
#define per(i,r,l) for(int i=(r),_=(l);i>=_;i--)
#define MS(arr,x) memset(arr,x,sizeof(arr))
#define INE(i,u) for(int i=head[u];~i;i=e[i].next)
#define LL long long
#define MP make_pair
#define X first
#define Y second
typedef pair<int,int>pii;
inline const int read()
{int r=0,k=1;char c=getchar();for(;c<'0'||c>'9';c=getchar())if(c=='-')k=-1;
for(;c>='0'&&c<='9';c=getchar())r=r*10+c-'0';return k*r;}
inline void MAX(int &a,int b){if(a<b)a=b;}

const int N=100010;
const int inf=0x3f3f3f3f;
int n;
struct edge{int v,w,next;}e[N*2];
int head[N],k;
bool sup[N];
int cnt[N],mx[N],size,rt;
bool flag[N];
int dp[N]; // ans
pii mi[N],cur;
vector<pii>S; // c#!¥f%@#...¥$%¥2&... 据说vector自带分块 

void adde(int u,int v,int w)
{
	e[k].v=v;
	e[k].w=w;
	e[k].next=head[u];
	head[u]=k++;
}
void getroot(int u,int fa)
{
	cnt[u]=1; mx[u]=0;
	INE(i,u)
	{
		int v=e[i].v; if(v==fa || flag[v]) continue;
		getroot(v,u);
		cnt[u]+=cnt[v];
		MAX(mx[u],cnt[v]);
	}
	MAX(mx[u],size-cnt[u]);
	if(mx[u] < mx[rt]) rt=u;
}
void addans(int u,int fa,int dis)
{
	if(sup[u]) cur=min(cur,MP(dis,u));
	else INE(i,u) // ! 
	{
		int v=e[i].v; if(v==fa || flag[v]) continue;
		addans(v,u,dis+e[i].w);
	}
}
void add(int u,int fa,int dis)
{
	if(!sup[u]) mi[u]=min(mi[u],MP(cur.X+dis,cur.Y));
	INE(i,u)
	{
		int v=e[i].v; if(v==fa || flag[v]) continue;
		add(v,u,dis+e[i].w);
	}
}
void cal1(int u) // 并不知道怎么写,那就暴力的写吧QwQ 好丑陋 
{
    static vector<pii>son; rep(i,0,son.size()-1) son.pop_back();
	INE(i,u)
	{
		int v=e[i].v; if(flag[v]) continue;
		son.push_back(MP(v,e[i].w));
	}
	
	if(sup[u]) cur=MP(0,u);
	else cur=MP(inf,inf);
	rep(i,0,son.size()-1)
	{
		int v=son[i].X,w=son[i].Y;
		addans(v,u,w);
		add(v,u,w);
	}
	if(!sup[u]) mi[u]=min(mi[u],cur);
	
	if(sup[u]) cur=MP(0,u);
	else cur=MP(inf,inf);
	per(i,son.size()-1,0)
	{
		int v=son[i].X,w=son[i].Y;
		addans(v,u,w);
		add(v,u,w);
	}
	if(!sup[u]) mi[u]=min(mi[u],cur);
}
void divide(int u)
{
	flag[u]=1;
	cal1(u);
	INE(i,u)
	{
		int v=e[i].v; if(flag[v]) continue;
		size=mx[rt=0]=cnt[v];
		getroot(v,u);
		divide(rt);
	}
}
void insert(pii x)
{
	S.insert(lower_bound(S.begin(),S.end(),x),x);
}
int getrank(int dis,int u)
{
	return S.end()-lower_bound(S.begin(),S.end(),MP(dis,u));
}
void addans2(int u,int fa,int dis)
{
	if(!sup[u]) dp[u]+=getrank(dis,u);
	INE(i,u)
	{
		int v=e[i].v; if(v==fa || flag[v]) continue;
		addans2(v,u,dis+e[i].w);
	}
}
void add2(int u,int fa,int dis)
{
	if(!sup[u]) if(mi[u].X-dis>=0) insert(MP(mi[u].X-dis,mi[u].Y));
	INE(i,u)
	{
		int v=e[i].v; if(v==fa || flag[v]) continue;
		add2(v,u,dis+e[i].w);
	}
}
void cal2(int u) // 还是不知道怎么写 
{
    static vector<pii>son; rep(i,0,son.size()-1) son.pop_back();
	INE(i,u)
	{
		int v=e[i].v; if(flag[v]) continue;
		son.push_back(MP(v,e[i].w));
	}
	
	S.clear();
	if(!sup[u]) insert(MP(mi[u].X,mi[u].Y));
	rep(i,0,son.size()-1)
	{
		int v=son[i].X,w=son[i].Y;
		addans2(v,u,w);
		add2(v,u,w);
	}
	if(!sup[u]) dp[u]+=getrank(0,u);
	
	S.clear();
	per(i,son.size()-1,0)
	{
		int v=son[i].X,w=son[i].Y;
		addans2(v,u,w);
		add2(v,u,w);
	}
}
void divide2(int u)
{
	flag[u]=1;
	cal2(u);
	INE(i,u)
	{
		int v=e[i].v; if(flag[v]) continue;
		size=mx[rt=0]=cnt[v];
		getroot(v,u);
		divide2(rt);
	}
}

void input()
{
	rep(i,1,n) head[i]=-1,flag[i]=0,dp[i]=0,mi[i]=MP(inf,inf); k=0;
    rep(i,2,n)
    {
    	int u=read(),v=read(),w=read();
    	adde(u,v,w); adde(v,u,w);
    }
    rep(i,1,n) sup[i]=read();
}
void solve()
{
	size=mx[rt=0]=n;
	getroot(1,0);
	divide(rt);
	
	MS(flag,0);
	size=mx[rt=0]=n;
	getroot(1,0);
	divide2(rt);
	
	int ans=0;
	rep(i,1,n) if(!sup[i]) MAX(ans,dp[i]);
	printf("%d\n",ans);
	//rep(i,1,n) printf("%d\n",mi[i].Y);
}

int main()
{
    while(~scanf("%d",&n))
    input(),solve();
    return 0;
}

I

动态树分治先放着


J

不会


K

整体二分

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
#define rep(i,l,r) for(int i=(l),_=(r);i<=_;i++)
#define per(i,r,l) for(int i=(r),_=(l);i>=_;i--)
#define MS(arr,x) memset(arr,x,sizeof(arr))
#define INE(i,u) for(int i=head[u];~i;i=e[i].next)
#define LL long long
inline const int read()
{int r=0,k=1;char c=getchar();for(;c<'0'||c>'9';c=getchar())if(c=='-')k=-1;
for(;c>='0'&&c<='9';c=getchar())r=r*10+c-'0';return k*r;}
void MAX(int &a,int b){if(a<b)a=b;}
void MIN(int &a,int b){if(a>b)a=b;}

const int inf=0x3f3f3f3f;
const int N=50005;
const int Q=10010;
int n,m;
int a[N],mi,mx;
struct data{int x,y,z,op,id,cur,delta;}q[N+Q*2];
int tot;
int ans[Q];
int mid;
int c[N];

void add(int o,int x){for(;o<=n;o+=o&-o)c[o]+=x;}
int query(int o){int s=0;for(;o;o-=o&-o)s+=c[o];return s;}
bool part(data &x)
{
	if(x.op==3)
	{
		if(x.cur+x.delta>=x.z) return 1;
		x.cur+=x.delta; x.delta=0;
		return 0;
	}
	return x.y<=mid;
}
void cal(int l,int r,int L,int R)
{
	if(L==R)
	{
		rep(i,l,r) if(q[i].op==3) ans[q[i].id]=L;
		return;
	}
	mid=L+R>>1;
	rep(i,l,r)
	{
		if(q[i].op==1 && q[i].y<=mid) add(q[i].x,1);
		if(q[i].op==2 && q[i].y<=mid) add(q[i].x,-1);
		if(q[i].op==3) q[i].delta=query(q[i].y)-query(q[i].x-1);
	}
	rep(i,l,r)
	{
		if(q[i].op==1 && q[i].y<=mid) add(q[i].x,-1);
		if(q[i].op==2 && q[i].y<=mid) add(q[i].x,1);
	}
	int div=stable_partition(&q[l],&q[r+1],part)-&q[1];
	if(l<=div) cal(l,div,L,mid);
	if(div+1<=r) cal(div+1,r,mid+1,R);
}

void input()
{
	mi=inf; mx=-inf; tot=0; *ans=0;
	
    n=read(); m=read();
    rep(i,1,n)
    {
    	a[i]=read(); MAX(mx,a[i]); MIN(mi,a[i]);
    	q[++tot]=(data){i,a[i],0,1,0,0};
    }
    rep(i,1,m)
    {
    	char op[3]; scanf("%s",op);
    	if(op[0] == 'C')
    	{
    		int pos=read(),x=read();
    		q[++tot]=(data){pos,a[pos],0,2,0,0,0};
    		a[pos]=x; MAX(mx,x); MIN(mi,x);
    		q[++tot]=(data){pos,a[pos],0,1,0,0,0};
    	}
    	else
    	{
    		int l=read(),r=read(),k=read();
    		q[++tot]=(data){l,r,k,3,++*ans,0,0};
    	}
    }
}
void solve()
{
	cal(1,tot,mi,mx);
	rep(i,1,*ans) printf("%d\n",ans[i]);
}

int main()
{
    rep(i,1,read())
    input(),solve();
    return 0;
}


M

还是我写得最长QwQ


N

转化为矩形面积并,怎么反应慢了


O

可持久化线段树,不太会


P

树上的主席树

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
#define rep(i,l,r) for(int i=(l),_=(r);i<=_;i++)
#define per(i,r,l) for(int i=(r),_=(l);i>=_;i--)
#define MS(arr,x) memset(arr,x,sizeof(arr))
#define INE(i,u) for(int i=head[u];~i;i=e[i].next)
#define LL long long
inline const int read()
{int r=0,k=1;char c=getchar();for(;c<'0'||c>'9';c=getchar())if(c=='-')k=-1;
for(;c>='0'&&c<='9';c=getchar())r=r*10+c-'0';return k*r;}

const int N=100010;
int n,m;
int w[N],t[N],tot;
struct edge{int v,next;}e[N*2];
int head[N],k;
int in[N],_in[N],ind;
int fa[N][17],dep[N];
int root[N],sz;
int ls[N*20],rs[N*20],sum[N*20];

void adde(int u,int v){e[k]=(edge){v,head[u]};head[u]=k++;}
int find(int x)
{
	int l=1,r=tot,mid;
	while(l<r)
	{
		mid=l+r+1>>1;
		if(x<t[mid]) r=mid-1;
		else l=mid;
	}
	return l;
}
void dfs(int u)
{
	in[u]=++ind; _in[in[u]]=u;
	INE(i,u)
	{
		int v=e[i].v; if(v==fa[u][0]) continue;
		fa[v][0]=u; rep(i,1,16) fa[v][i]=fa[fa[v][i-1]][i-1];
		dep[v]=dep[u]+1;
		dfs(v);
	}
}
int lca(int a,int b)
{
	if(dep[a]<dep[b]) swap(a,b);
	int d=dep[a]-dep[b];
	rep(i,0,16) if(d>>i&1) a=fa[a][i];
	if(a==b) return a;
	per(i,16,0) if(fa[a][i]^fa[b][i]) a=fa[a][i],b=fa[b][i];
	return fa[a][0];
}
void update(int &o,int lst,int x,int L,int R)
{
	o=++sz; sum[o]=sum[lst]+1; ls[o]=ls[lst]; rs[o]=rs[lst];
	if(L==R) return;
	int mid=L+R>>1;
	if(x<=mid) update(ls[o],ls[lst],x,L,mid);
	else update(rs[o],rs[lst],x,mid+1,R);
}
int getans(int x,int y,int k)
{
	int anc=lca(x,y),f=fa[anc][0];
	int a=root[in[x]],b=root[in[y]],c=root[in[anc]],d=root[in[f]];
	int l=1,r=tot;
	while(l<r)
	{
		int mid=l+r>>1;
		int cnt=sum[ls[a]]+sum[ls[b]]-sum[ls[c]]-sum[ls[d]];
		if(cnt>=k) a=ls[a],b=ls[b],c=ls[c],d=ls[d],r=mid;
		else a=rs[a],b=rs[b],c=rs[c],d=rs[d],l=mid+1,k-=cnt;
	}
	return t[l];
}

void input()
{
	MS(head,-1);
    n=read(); m=read();
    rep(i,1,n) t[i]=w[i]=read();
    sort(&t[1],&t[n+1]);
    tot=unique(&t[1],&t[n+1])-t-1;
    rep(i,1,n) w[i]=find(w[i]);
    
    rep(i,2,n)
    {
    	int u=read(),v=read();
    	adde(u,v); adde(v,u);
    }
}
void solve()
{
	dfs(1);
	rep(i,1,n)
	{
		int u=_in[i];
		update(root[i],root[in[fa[u][0]]],w[u],1,tot);
	}
	while(m--)
	{
		int u=read(),v=read(),k=read();
		printf("%d\n",getans(u,v,k));
	}
}

int main()
{
    input(),solve();
    return 0;
}


U

LCT

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
#define rep(i,l,r) for(int i=(l),_=(r);i<=_;i++)
#define per(i,r,l) for(int i=(r),_=(l);i>=_;i--)
#define MS(arr,x) memset(arr,x,sizeof(arr))
#define INE(i,u) for(int i=head[u];~i;i=e[i].next)
#define LL long long
#define LS c[0]
#define RS c[1]
inline const int read()
{int r=0,k=1;char c=getchar();for(;c<'0'||c>'9';c=getchar())if(c=='-')k=-1;
for(;c>='0'&&c<='9';c=getchar())r=r*10+c-'0';return k*r;}
void MIN(int &a,int b){if(a>b)a=b;}
void MAX(int &a,int b){if(a<b)a=b;}

const int inf=0x3f3f3f3f;
const int N=50005;
int n;
struct node *null;
struct node{
	node *c[2],*fa;
	bool d(){return this==fa->RS;}
	void setc(node *ch,bool d){ch->fa=this;c[d]=ch;}
	bool isroot(){return this!=fa->LS && this!=fa->RS;}
	
	bool rev;
	int w;
	int slr,srl;
	int mil,mir,mi;
	int mxl,mxr,mx;
	int add;
	void Setv(int x)
	{
		w=mil=mir=mxl=mxr=mi=mx=x;
	}
	void Add(int x)
	{
		if(this==null) return;
		w+=x; add+=x;
		mil+=x; mir+=x; mi+=x;
		mxl+=x; mxr+=x; mx+=x;
	}
	void Flip()
	{
		if(this==null) return;
		rev^=1; swap(LS,RS);
		swap(slr,srl);
	}
	void down()
	{
		if(add)
		{
			LS->Add(add);
			RS->Add(add);
			add=0;
		}
		if(rev)
		{
			LS->Flip();
			RS->Flip();
			rev=0;
		}
	}
	void up()
	{
		mil=mir=mxl=mxr=mi=mx=w;
		slr=srl=0;
		if(LS!=null)
		{
			MIN(mil,LS->mi);
			MAX(mxl,LS->mx);
			MAX(slr,LS->slr);
			MAX(srl,LS->srl);
		}
		if(RS!=null)
		{
			MIN(mir,RS->mi);
			MAX(mxr,RS->mx);
			MAX(slr,RS->slr);
			MAX(srl,RS->srl);
		}
		mi=min(mil,mir);
		mx=max(mxl,mxr);
		MAX(slr,mxr-mil);
		MAX(srl,mxl-mir);
	}
	void init()
	{
		LS=RS=fa=null;
		rev=0;
		w=0;
		slr=srl=0;
		mi=mil=mir=inf;
		mx=mxl=mxr=-inf;
		add=0;
	}
}T[N];

void rot(node *o)
{
	node *f=o->fa;
	f->down(); o->down();
	bool d=o->d();
	if(!f->isroot()) f->fa->setc(o,f->d());
	else o->fa=f->fa;
	f->setc(o->c[!d],d); o->setc(f,!d);
	f->up();
}
void splay(node *o)
{
	for(o->down();!o->isroot();rot(o));
	o->up();
}
void access(node *o)
{
	for(node *t=null;o!=null;t=o,o=o->fa)
	    splay(o),o->RS=t;
}
void makeroot(node *o)
{
	access(o); splay(o); o->Flip();
}
void split(node *x,node *y)
{
	makeroot(x); access(y); splay(y);
}
void link(node *x,node *y)
{
	makeroot(x); x->fa=y;
}

void input()
{
    n=read();
    null=&T[0]; null->init();
    rep(i,1,n)
    {
    	T[i].init();
    	T[i].Setv(read());
    }
    rep(i,2,n)
    {
    	int u=read(),v=read();
    	link(&T[u],&T[v]);
    }
}
void solve()
{
	rep(__,1,read())
	{
		int u=read(),v=read(),x=read();
		split(&T[u],&T[v]);
		printf("%d\n",T[v].slr);
		T[v].Add(x);
	}
}

int main()
{
    rep(i,1,read())
    input(),solve();
    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值