线段树分治

文章目录

  • 口胡
  • bzoj4025: 二分图
  • loj534. 「LibreOJ Round #6」花团
  • bzoj4644. 经典傻逼题

口胡

发现还有好多我不知道的算法啊。。
大概就是给了一些条件,这些条件有开始生效的时间和失效的时间,然后询问某些时间段内,在条件限制下的答案。
做法是对时间段建线段树,把条件用类似按开始时间和结束时间区间查询的方式插入线段树,然后遍历整个线段树得到答案——我从我的父亲继承它的东西,然后加上我的条件,回溯的时候撤销我的条件。

bzoj4025: 二分图

どこでもドア
判断二分图可以染色,染好色的图怎么连边断边保持颜色,用带权并查集维护。每个点到父亲的边权为1/0表示是否和父亲同色。于是套上线段树分治就好了。

//Achen
#include
#define For(i,a,b) for(register int i=(a);i<=(b);i++)
#define Rep(i,a,b) for(register int i=(a);i>=(b);i--)
#define Formylove return 0
const int N=200007;
typedef long long LL;
typedef double db;
using namespace std;
int n,m,T;

template<typename T> void read(T &x) {
	char ch=getchar(); T f=1; x=0;
	while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
	if(ch=='-') f=-1,ch=getchar();
	for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
}

#define pr pair
#define MP make_pair
#define se second
#define fi first
vector<pr>vc[N<<2];
vector<int>cx[N<<2];

#define lc (x<<1)
#define rc ((x<<1)|1)
#define mid ((l+r)>>1)
void add(int x,int l,int r,int ql,int qr,int u,int v) {
	if(l>=ql&&r<=qr) {
		vc[x].push_back(MP(u,v));
		return ;
	}
	if(ql<=mid) add(lc,l,mid,ql,qr,u,v);
	if(qr>mid) add(rc,mid+1,r,ql,qr,u,v);
}

int fa[N],fg[N];
pr find(int x) {
	if(x==fa[x]) return MP(x,0);
	pr t=find(fa[x]);
	return MP(t.fi,t.se+fg[x]);
}

int no[N];
void qry(int x,int l,int r) {
	int up=vc[x].size(),fl=1;
	For(i,0,up-1) {
		pr e=vc[x][i];
		int u=e.fi,v=e.se;
		pr t1=find(u),t2=find(v);
		if(t1.fi==t2.fi) {
			if(t1.se%2==t2.se%2) { fl=0; break; }
			else continue;
		}
		else {
			fa[t1.fi]=t2.fi;
			fg[t1.fi]=(t1.se%2==t2.se%2);
			cx[x].push_back(t1.fi);
		}
	}
	if(!fl) For(i,l,r) no[i]=1; 	
	if(l!=r&&fl) { qry(lc,l,mid); qry(rc,mid+1,r); }
	up=cx[x].size();
	Rep(i,up-1,0) fa[cx[x][i]]=cx[x][i];
}

int main() {
    //freopen("1.in","r",stdin);
    //freopen("1.out","w",stdout);
	read(n); read(m); read(T);
	For(i,1,n) fa[i]=i,fg[i]=0;
	For(i,1,m) {
		int u,v,s,t;
		read(u); read(v);
		read(s); read(t);
		if(s+1<=t) add(1,1,T,s+1,t,u,v);
	}
	qry(1,1,T);
	For(i,1,T) if(!no[i]) puts("Yes"); else puts("No");
	Formylove;
}

loj534. 「LibreOJ Round #6」花团

どこでもドア
这个充满奥妙的算法,看上去是离线的实际上却是资瓷强制在线?
新加入的修改都在当前询问的后面,我们在线段树上一边走一边读。读到修改就一直改直到读到询问,读到询问就在线段树上走啊走,走到询问的地方回答了然后继续读入。
更加奥妙重重的是这道题用线段树分治这样搞是 1500 0 2 l o g 15000^2log 150002log的(不满),然鹅却可以过??

//Achen
#include
#define For(i,a,b) for(register int i=(a);i<=(b);i++)
#define Rep(i,a,b) for(register int i=(a);i>=(b);i--)
#define Formylove return 0
const int N=15007;
typedef long long LL;
typedef double db;
using namespace std;
int T,V,oo,nowti,lastans;

template<typename T> void read(T &x) {
	char ch=getchar(); T f=1; x=0;
	while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
	if(ch=='-') f=-1,ch=getchar();
	for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
}

#define pr pair
#define MP make_pair
#define se second
#define fi first
vector<pr>vc[N<<2];
int f[20][N];

#define lc (x<<1)
#define rc ((x<<1)|1)
#define mid ((l+r)>>1)
void add(int x,int l,int r,int ql,int qr,int v,int w) {
	if(l>=ql&&r<=qr) {
		vc[x].push_back(MP(v,w));
		return ;
	}
	if(ql<=mid) add(lc,l,mid,ql,qr,v,w);
	if(qr>mid) add(rc,mid+1,r,ql,qr,v,w);
}

int op,vv,ww,tt;
void get_read() {
	while(nowti<T) {
		nowti++;
		read(op); read(vv); vv-=oo*lastans;
		if(op==1) { 
			read(ww); read(tt); 
			ww-=oo*lastans; tt-=oo*lastans;
			if(tt>=nowti) add(1,1,T,nowti,tt,vv,ww);
		}
		else break;
	}
}

void qry(int x,int l,int r,int dep) {
	For(i,0,V) f[dep][i]=f[dep-1][i];
	int up=vc[x].size();
	For(i,0,up-1) {
		pr t=vc[x][i];
		int v=t.fi,w=t.se;
		Rep(i,V,v) f[dep][i]=max(f[dep][i],f[dep][i-v]+w);
	}
	if(l!=r) {
		if(nowti>=1&&nowti<=mid) qry(lc,l,mid,dep+1);
		if(nowti>mid&&nowti<=r) qry(rc,mid+1,r,dep+1);
	}
	else if(op==2&&l==nowti) {
		int t1,t2;
		if(f[dep][vv]>=0) t1=1,t2=f[dep][vv];
		else t1=t2=0;
		printf("%d %d\n",t1,t2);
		lastans=(t1^t2); get_read();
	}
}

int main() {
    //freopen("1.in","r",stdin);
    //freopen("1.out","w",stdout);
	read(T); read(V); read(oo);
	get_read();
	memset(f,128,sizeof(f));
	f[0][0]=0;
	qry(1,1,T,1);
	Formylove;
}

bzoj4644. 经典傻逼题

どこでもドア
看了下数据范围这不是暴力线性基吗??懵逼
再仔细一看,数的位数L<=1000。
因为点权要修改,就要把一个数删除加入另一个,而线性基不太资瓷删除一个数,考虑线段树分治。
每个点在一段区间内保持同一个值,就在线段树上加入条件:在这段区间加入这个值。于是现在的条件全是加入,线段树分治每次继承父亲的线性基即可。
用bitset优化一下。

//Achen
#include
#define For(i,a,b) for(register int i=(a);i<=(b);i++)
#define Rep(i,a,b) for(register int i=(a);i>=(b);i--)
#define Formylove return 0
const int N=1007;
typedef long long LL;
typedef double db;
using namespace std;
int ID,n,m,prt[N],UP;

template<typename T> void read(T &x) {
	char ch=getchar(); T f=1; x=0;
	while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
	if(ch=='-') f=-1,ch=getchar();
	for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
}

#define BT bitset
vector<BT>vc[N<<2];
BT prv[N],w,ans;
char s[N];
void getw() {
	scanf("%s",s); w.reset();
	int len=strlen(s);
	UP=max(UP,len-1);
	Rep(i,len-1,0) 
		if(s[i]=='1') w.set(len-i-1);
}

void print(BT A) {
	int st=UP;
	while(st&&!A.test(st)) st--;
	while(st>=0) {
		if(A.test(st)) putchar('1');
		else putchar('0'); st--;
	} puts("");
}

#define lc (x<<1)
#define rc ((x<<1)|1)
#define mid ((l+r)>>1)
void add(int x,int l,int r,int ql,int qr,int v) {
	if(ql>qr) return ;
	if(l>=ql&&r<=qr) {
		vc[x].push_back(prv[v]);
		return ;
	}
	if(ql<=mid) add(lc,l,mid,ql,qr,v);
	if(qr>mid) add(rc,mid+1,r,ql,qr,v);
}

BT b[12][N];
void qry(int x,int l,int r,int dep) {
	int up=vc[x].size();
	For(i,0,UP) b[dep][i]=b[dep-1][i];
	For(i,0,up-1) {
		BT v=vc[x][i]; 
		//printf("%d %d ",l,r); print(v);
		Rep(j,UP,0) if(v.test(j)) {
			if(b[dep][j].test(j)) v^=b[dep][j];
			else { b[dep][j]=v; break; }
		}
	}
	if(l==r) {
		ans.reset();
		Rep(i,UP,0) if(!ans.test(i)) ans^=b[dep][i];
		print(ans); 
		return;
	}
	qry(lc,l,mid,dep+1); qry(rc,mid+1,r,dep+1); 
}

int main() {
    freopen("4644.in","r",stdin);
    freopen("4644.out","w",stdout);
	read(ID);
	read(n); read(m);
	For(i,1,n) prt[i]=1;
	For(i,1,m) {
		int u,v;
		read(u); read(v); getw(); //print(w);
		add(1,1,m,prt[u],i-1,u); prv[u]^=w; prt[u]=i;
		add(1,1,m,prt[v],i-1,v); prv[v]^=w; prt[v]=i;
	}
	For(i,1,n) add(1,1,m,prt[i],m,i);
	qry(1,1,m,1);
	Formylove;
}

你可能感兴趣的:(数据结构)