发现还有好多我不知道的算法啊。。
大概就是给了一些条件,这些条件有开始生效的时间和失效的时间,然后询问某些时间段内,在条件限制下的答案。
做法是对时间段建线段树,把条件用类似按开始时间和结束时间区间查询的方式插入线段树,然后遍历整个线段树得到答案——我从我的父亲继承它的东西,然后加上我的条件,回溯的时候撤销我的条件。
どこでもドア
判断二分图可以染色,染好色的图怎么连边断边保持颜色,用带权并查集维护。每个点到父亲的边权为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;
}
どこでもドア
这个充满奥妙的算法,看上去是离线的实际上却是资瓷强制在线?
新加入的修改都在当前询问的后面,我们在线段树上一边走一边读。读到修改就一直改直到读到询问,读到询问就在线段树上走啊走,走到询问的地方回答了然后继续读入。
更加奥妙重重的是这道题用线段树分治这样搞是 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;
}
どこでもドア
看了下数据范围这不是暴力线性基吗??懵逼
再仔细一看,数的位数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;
}