@Plutorabbit
2017-02-19T11:05:55.000000Z
字数 7644
阅读 1875
未分类
BZOJ 4537 ~ BZOJ 4542
分块+并查集
就是零散的部分用并查集来维护
但是不能路径压缩
因为要暴力撤回去。。。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstdlib>
#include <queue>
#include <cmath>
#include <cstring>
#define NN 50010
#define MM 100010
using namespace std;
struct Edge
{
int x,y,a,b,id;
}e[MM],q[MM],tmp[MM];
int fa[MM],n,m,sz[MM],Q,tot,ma[MM],mb[MM],block,k;
bool vis[MM]={0};
struct PRE
{
int x,y,sz,fa,yma,ymb,f,xma,xmb;
}pre[MM];
void read(int &xx)
{
bool f=0; char CH;
for (CH=getchar();CH<'0'||CH>'9';CH=getchar()) if (CH=='-') f=1;
for (xx=0;CH>='0';CH=getchar()) xx=xx*10+CH-'0'; if (f) xx=-xx;
}
bool cmp1(Edge xx,Edge yy) { if (xx.a==yy.a) return xx.b<yy.b; else return xx.a<yy.a;}
bool cmp2(Edge xx,Edge yy) { if (xx.b==yy.b) return xx.a<yy.a; else return xx.b<yy.b;}
int Find(int xx) { return (xx==fa[xx]?xx:Find(fa[xx]));}
void Doit(int x,int y,int a,int b)
{
int xx=Find(x), yy=Find(y);
if (sz[xx]>sz[yy]) swap(xx,yy);
pre[++tot].x=xx, pre[tot].y=yy, pre[tot].f=fa[xx], pre[tot].sz=sz[yy];
pre[tot].yma=ma[yy], pre[tot].ymb=mb[yy], pre[tot].xma=ma[xx], pre[tot].xmb=mb[xx];
if (xx==yy)
{
ma[yy]=max(ma[yy],a), mb[yy]=max(mb[yy],b); return;
}
fa[xx]=yy, sz[yy]+=sz[xx], ma[yy]=max(ma[yy],max(ma[xx],a)), mb[yy]=max(mb[yy],max(mb[xx],b));
}
void Back()
{
for (;tot;tot--)
{
fa[pre[tot].x]=pre[tot].f, ma[pre[tot].x]=pre[tot].xma, mb[pre[tot].x]=pre[tot].xmb;
sz[pre[tot].y]=pre[tot].sz, ma[pre[tot].y]=pre[tot].yma, mb[pre[tot].y]=pre[tot].ymb;
}
}
int main()
{
read(n), read(m);
for (int i=1;i<=m;++i) read(e[i].x), read(e[i].y), read(e[i].a), read(e[i].b), e[i].id=i;
read(Q);
for (int i=1;i<=Q;++i) read(q[i].x), read(q[i].y), read(q[i].a), read(q[i].b), q[i].id=i;
sort(e+1,e+1+m,cmp1); sort(q+1,q+1+Q,cmp2);
block=(int)sqrt(m);
for (int i=1;i<=m;i+=block)
{
k=0;
for (int j=1;j<=Q;++j)
if (q[j].a>=e[i].a && (i+block>m || q[j].a<e[i+block].a)) tmp[++k]=q[j];
if (!k) continue;
sort(e+1,e+i,cmp2);
for (int j=1;j<=n;++j) fa[j]=j, sz[j]=1, ma[j]=mb[j]=-1;
for (int j=1,t=1;j<=k;++j)
{
for (;t<i && e[t].b<=tmp[j].b;t++) Doit(e[t].x,e[t].y,e[t].a,e[t].b);
tot=0;
for (int l=i;l<i+block&&l<=m;++l)
if (e[l].a<=tmp[j].a && e[l].b<=tmp[j].b) Doit(e[l].x,e[l].y,e[l].a,e[l].b);
int xx=Find(tmp[j].x), yy=Find(tmp[j].y);
if (xx==yy && ma[xx]==tmp[j].a && mb[xx]==tmp[j].b) vis[tmp[j].id]=1;
Back();
}
}
for (int i=1;i<=Q;++i) if (vis[i]) puts("Yes"); else puts("No");
return 0;
}
树剖上乱搞
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <queue>
#define INF 0x3f3f3f3f
#define NN 100010
using namespace std;
struct Edge
{
int ne,u,v;
}e[NN<<1];
struct A
{
int x,y;
}a[110];
bool operator <(A xx,A yy) { return xx.x<yy.x;}
int n,m,num,numm=0,tot=0,ans=0,cnt,now,x,y,op;
int pos[NN],son[NN],fa[NN],sz[NN],deep[NN],head[NN],anc[NN];
bool flag[NN<<1];
priority_queue<A> que[300010];
int read()
{
int xx; bool f=0; char CH;
for (CH=getchar();CH<'0'||CH>'9';CH=getchar()) if (CH=='-') f=1;
for (xx=0;CH>='0';CH=getchar()) xx=xx*10+CH-'0'; if (f) xx=-xx;
return xx;
}
void Build(int xx,int yy)
{
e[++tot].ne=head[xx], head[xx]=tot, e[tot].v=yy, e[tot].u=xx;
e[++tot].ne=head[yy], head[yy]=tot, e[tot].v=xx, e[tot].u=yy;
}
void DFS1(int xx)
{
sz[xx]=1;
for (int i=head[xx];i;i=e[i].ne)
if (e[i].v!=fa[xx])
{
fa[e[i].v]=xx, deep[e[i].v]=deep[xx]+1;
DFS1(e[i].v);
sz[xx]+=sz[e[i].v];
if (sz[e[i].v]>sz[son[xx]]) son[xx]=e[i].v;
}
}
void DFS2(int xx,int chain)
{
pos[xx]=++numm, anc[xx]=chain;
if (son[xx]) DFS2(son[xx],chain);
for (int i=head[xx];i;i=e[i].ne)
if (e[i].v!=son[xx] && e[i].v!=fa[xx]) DFS2(e[i].v,e[i].v);
}
void Query(int k,int l,int r,int x)
{
while (!que[k].empty() && flag[que[k].top().y]) que[k].pop();
if (!que[k].empty()) ans=max(ans,que[k].top().x);
if (l<r)
{
int mid=(l+r)>>1;
if (x<=mid) Query(k<<1,l,mid,x); else Query(k<<1|1,mid+1,r,x);
}
}
void Insert(int k,int l,int r,int x,int y)
{
if (l==x && r==y) { que[k].push(A{num,now}); return; }
int mid=(l+r)>>1;
if (y<=mid) Insert(k<<1,l,mid,x,y);
else if (x>mid) Insert(k<<1|1,mid+1,r,x,y);
else Insert(k<<1,l,mid,x,mid), Insert(k<<1|1,mid+1,r,mid+1,y);
}
int main()
{
n=read(), m=read();
for (int i=1;i<n;++i) x=read(), y=read(), Build(x,y);
DFS1(1), DFS2(1,1);
for (now=1;now<=m;++now)
{
op=read();
if (op==0)
{
x=read(), y=read(), num=read(), cnt=0;
for (;anc[x]!=anc[y];x=fa[anc[x]])
{
if (deep[anc[x]]<deep[anc[y]]) swap(x,y);
a[++cnt].x=pos[anc[x]], a[cnt].y=pos[x];
}
if (deep[x]>deep[y]) swap(x,y);
a[++cnt].x=pos[x], a[cnt].y=pos[y];
sort(a+1,a+1+cnt);
for (int i=1;i<=cnt;++i)
if (a[i-1].y+1<a[i].x) Insert(1,1,n,a[i-1].y+1,a[i].x-1);
if (a[cnt].y<n) Insert(1,1,n,a[cnt].y+1,n);
}
else if (op==1) flag[read()]=1;
else ans=-1, Query(1,1,n,pos[read()]), printf("%d\n",ans);
}
return 0;
}
树上乱搞QAQ
感觉不想写就烂这了
莫队+rmq统计
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <queue>
#define INF 0x3f3f3f3f
#define NN 100010
#define LL long long
using namespace std;
struct Query
{
int l,r,id;
}q[NN];
int st[NN],a[NN],l[NN],r[NN],f[NN][20],n,m,top=0,block,Log[NN];
LL ans[NN],now,ld[NN],rd[NN];
bool cmp1(Query xx,Query yy)
{
if (xx.l/block==yy.l/block) return xx.r<yy.r;
else return xx.l/block<yy.l/block;
}
int read()
{
int xx; bool f=0; char CH;
for (CH=getchar();CH<'0'||CH>'9';CH=getchar()) if (CH=='-') f=1;
for (xx=0;CH>='0';CH=getchar()) xx=xx*10+CH-'0'; if (f) xx=-xx;
return xx;
}
int Q(int x,int y)
{
int tmpp=(int)log2(y-x+1);
if (a[f[x][tmpp]]<a[f[y-(1<<tmpp)+1][tmpp]]) return f[x][tmpp];
else return f[y-(1<<tmpp)+1][tmpp];
}
void L_(int x,int y,LL t)
{
int tmp=Q(x,y);
now+=t*a[tmp]*(y-tmp+1)+t*(rd[x]-rd[tmp]);
}
void R_(int x,int y,LL t)
{
int tmp=Q(x,y);
now+=t*a[tmp]*(tmp-x+1)+t*(ld[y]-ld[tmp]);
}
void pre()
{
for (int i=1;i<=n;++i)
{
while (top && a[st[top]]>a[i]) r[st[top--]]=i;
if (a[st[top]]==a[i]) l[i]=l[st[top]]; else l[i]=st[top];
st[++top]=i;
}
while (top) r[st[top--]]=n+1;
for (int i=1;i<=n;++i) ld[i]=ld[l[i]]+1ll*(i-l[i])*a[i];
for (int i=n;i>=1;--i) rd[i]=rd[r[i]]+1ll*(r[i]-i)*a[i];
for (int i=1;i<=n;++i) f[i][0]=i;
for (int i=1;(1<<i)<=n;++i)
for (int j=1;j<=n-(1<<i)+1;j++)
{
if (a[f[j][i-1]]<a[f[j+(1<<(i-1))][i-1]]) f[j][i]=f[j][i-1];
else f[j][i]=f[j+(1<<(i-1))][i-1];
}
}
int main()
{
n=read(), m=read();
block=(int)sqrt(n);
for (int i=1;i<=n;++i) a[i]=read();
pre();
for (int i=1;i<=m;++i) q[i].l=read(), q[i].r=read(), q[i].id=i;
sort(q+1,q+1+m,cmp1);
int x=1,y=1;
now=a[1];
for (int i=1;i<=m;++i)
{
if (q[i].r>y) while (y!=q[i].r) y++, R_(x,y,1);
if (q[i].l>x) while (x!=q[i].l) L_(x,y,-1), x++;
if (q[i].l<x) while (x!=q[i].l) x--, L_(x,y,1);
if (q[i].r<y) while (y!=q[i].r) R_(x,y,-1), y--;
ans[q[i].id]=now;
}
for (int i=1;i<=m;++i) printf("%lld\n",ans[i]);
return 0;
}
听说对偶图乱搞QAQ
不会。。。
输出-1得10分蛤蛤
又双是莫队
且 时:统计模下前缀和即可
且 时:暴力讨论即可
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int NN = 100005;
struct Q
{
int l,r,id;
}q[NN];
LL mod,ans[NN],a[NN],bin[NN],b[NN],c[NN],pos[NN],cnt[NN],cnt2[NN],sum2[NN],now = 0;
int tot,m,n,block;
char ch[NN];
inline bool cmp(Q xx,Q yy) { return (pos[xx.l] != pos[yy.l]) ? xx.l < yy.l : xx.r < yy.r; }
inline void modify(int p,int op)
{
now -= cnt[b[p]] * (cnt[b[p]]-1) / 2;
cnt[b[p]] += op;
now += cnt[b[p]] * (cnt[b[p]]-1) / 2;
}
void Solve1()
{
block = (int) sqrt(n);
bin[0] = 1; for (int i=1;i<=n+1;++i) bin[i] = bin[i-1] * 10ll % mod;
for (int i=1;i<=n;++i) pos[i] = (i-1)/block + 1;
for (int i=n;i;--i) b[i] = (b[i+1] + a[i] * bin[n-i]) % mod;
b[n+1] = 0;
memcpy(c,b,sizeof(c));
sort(c+1,c+n+2);
tot = unique(c+1,c+n+2) - c - 1;
for (int i=1;i<=n+1;++i) b[i] = lower_bound(c+1,c+n+2,b[i]) - c;
sort(q+1,q+m+1,cmp);
for (int i=1,l=1,r=0;i<=m;++i)
{
for (;r<q[i].r;++r) modify(r+1,1);
for (;r>q[i].r;--r) modify(r, -1);
for (;l<q[i].l;++l) modify(l, -1);
for (;l>q[i].l;--l) modify(l-1,1);
ans[q[i].id] = now;
}
for (int i=1;i<=m;++i) printf("%lld\n",ans[i]);
}
void Solve2()
{
for (int i=1;i<=n;++i) cnt2[i] = cnt2[i-1] + (a[i] % mod == 0), sum2[i] = sum2[i-1] + (a[i]%mod == 0 ? i : 0);
int x,y;
for (int i=1;i<=m;++i)
{
x = q[i].l, y = q[i].r-1;
printf("%lld\n",sum2[y] - sum2[x-1] - (LL)(x-1) * (cnt2[y]-cnt2[x-1]));
}
}
int main()
{
scanf("%lld%s%d",&mod,ch+1,&m);
n = strlen(ch+1);
for (int i=1;i<=n;++i) a[i] = ch[i] - '0';
for (int i=1;i<=m;++i) scanf("%d%d",&q[i].l,&q[i].r), ++q[i].r, q[i].id = i;
if (mod == 2 || mod == 5) Solve2(); else Solve1();
return 0;
}