学习了一下很基本的分块和莫队算法,因为不太会写曼哈顿距离最小生成树,所以就写了个分块版本的(分四种情况,大概这个意思吧)。。。
cogs1775||bzoj2038 小Z的袜子
题目大意:静态区间查询不同种元素的个数。
思路:用莫队扫一下,然后分子分母同时乘2,就会发现,分母是组合数化简后的(r-l)*(r-l+1),分子是每种颜色个数的平方-区间元素(从相同颜色的当中选两个可重的,去掉两个是一个的),然后就很好处理了。
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> using namespace std; struct use{ long long zi,mu; }ans[50001]={0}; struct used{ int p,ll,rr; }ask[50001]={0}; int a[50001]={0},num[50001]={0},len; int my_comp(const used &x,const used &y) { if (x.ll/len<y.ll/len) return 1; if (x.ll/len==y.ll/len&&x.rr<=y.rr) return 1; return 0; } long long gcd(long long x,long long y) { if (x%y==0) return y; else return gcd(y,x%y); } int main() { freopen("hose.in","r",stdin); freopen("hose.out","w",stdout); int n,m,i,j,block,l,r; long long sum; scanf("%d%d",&n,&m); len=floor(sqrt(n)); for (i=1;i<=n;++i) scanf("%d",&a[i]); for (i=1;i<=m;++i) { ask[i].p=i; scanf("%d%d",&ask[i].ll,&ask[i].rr); } sort(ask+1,ask+m+1,my_comp); l=1;r=0;sum=0; for (i=1;i<=m;++i) { while(r<ask[i].rr) { ++r;sum-=(long long)num[a[r]]*num[a[r]]; ++num[a[r]];sum+=(long long)num[a[r]]*num[a[r]]; } while(r>ask[i].rr) { sum-=(long long)num[a[r]]*num[a[r]];--num[a[r]]; sum+=(long long)num[a[r]]*num[a[r]];--r; } while(l<ask[i].ll) { sum-=(long long)num[a[l]]*num[a[l]];--num[a[l]]; sum+=(long long)num[a[l]]*num[a[l]];++l; } while(l>ask[i].ll) { --l;sum-=(long long)num[a[l]]*num[a[l]]; ++num[a[l]];sum+=(long long)num[a[l]]*num[a[l]]; } ans[ask[i].p].zi=sum-(ask[i].rr-ask[i].ll+1); ans[ask[i].p].mu=(long long)(ask[i].rr-ask[i].ll+1)*(ask[i].rr-ask[i].ll); } for (i=1;i<=m;++i) { if (ans[i].zi!=0) { sum=gcd(ans[i].zi,ans[i].mu); printf("%lld/%lld\n",ans[i].zi/sum,ans[i].mu/sum); } else printf("0/1\n"); } fclose(stdin); fclose(stdout); }
cogs1822||bzoj3236 作业
题目大意:静态查询区间内数字∈[a,b]的个数和数字的种数。
思路:同上,用权值树状数组维护一下就可以了。
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> using namespace std; struct use{ int ll,rr,aa,b,p,kk; }ask[1000001]={0}; int c1[100001]={0},c2[100001]={0},n,a[100001],len,ans[1000001][2]={0},visit[100001]={0}; int lowbit(int x) {return x&(-x);} int my_comp(const use &x,const use &y) { if (x.kk<y.kk) return 1; if (x.kk==y.kk&&x.rr<y.rr) return 1; return 0; } int bit_ask(int kind,int l,int r) { int sum=0; --l; if (kind==1) { for (;r;r-=lowbit(r)) sum+=c1[r]; for (;l;l-=lowbit(l)) sum-=c1[l]; } else { for (;r;r-=lowbit(r)) sum+=c2[r]; for (;l;l-=lowbit(l)) sum-=c2[l]; } return sum; } void bit_ins(int x) { int t;t=x; for (;t<=n;t+=lowbit(t)) c1[t]+=1; if (!visit[x]) for (;x<=n;x+=lowbit(x)) c2[x]+=1; } void bit_del(int x) { int t;t=x; for (;t<=n;t+=lowbit(t)) c1[t]-=1; if (!visit[x]) for (;x<=n;x+=lowbit(x)) c2[x]-=1; } int main() { freopen("ahoi2013_homework.in","r",stdin); freopen("ahoi2013_homework.out","w",stdout); int m,i,j,l,r; scanf("%d%d",&n,&m); len=floor(sqrt(n)); for (i=1;i<=n;++i) scanf("%d",&a[i]); for (i=1;i<=m;++i) { ask[i].p=i; scanf("%d%d%d%d",&ask[i].ll,&ask[i].rr,&ask[i].aa,&ask[i].b); ask[i].kk=ask[i].ll/len+1; } sort(ask+1,ask+m+1,my_comp); l=1;r=0; for (i=1;i<=m;++i) { while(r<ask[i].rr) { ++r;bit_ins(a[r]);++visit[a[r]]; } while(r>ask[i].rr) { --visit[a[r]];bit_del(a[r]);--r; } while(l<ask[i].ll) { --visit[a[l]];bit_del(a[l]);++l; } while(l>ask[i].ll) { --l;bit_ins(a[l]);++visit[a[l]]; } ans[ask[i].p][0]=bit_ask(1,ask[i].aa,ask[i].b); ans[ask[i].p][1]=bit_ask(2,ask[i].aa,ask[i].b); } for (i=1;i<=m;++i) printf("%d %d\n",ans[i][0],ans[i][1]); fclose(stdin); fclose(stdout); }
时间: 2024-10-11 16:39:07