@Plutorabbit
2017-02-19T03:05:55.000000Z
字数 7644
阅读 2045
未分类
BZOJ 4537 ~ BZOJ 4542
分块+并查集
就是零散的部分用并查集来维护
但是不能路径压缩
因为要暴力撤回去。。。
#include <iostream>#include <cstdio>#include <algorithm>#include <cstdlib>#include <queue>#include <cmath>#include <cstring>#define NN 50010#define MM 100010using 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 100010using 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 longusing 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;}