http://www.tuicool.com/articles/mEzqeaM
二分
1
Give you three sequences of numbers A, B, C, then we give
you a number X. Now you need to calculate if you can find
the three numbers Ai, Bj, Ck, which satisfy the formula
Ai+Bj+Ck = X.
1 ≤ L, N, M ≤ 500, 1 ≤ T ≤ 1000
枚举ai+bj,枚举k,再在ai+bj中二分找对应值。
2
你有 N 个物品,每个物品有 Ai,Bi 属性,要求选出 K 个物
品,使得
∑ i ϵ k A i ∑ i ϵ k B i \frac{\sum_{i\epsilon k} A_i}{\sum_{i\epsilon k} B_i} ∑iϵkBi∑iϵkAi
取max。
上述式子等价于 ∑ A i − B i ∗ a n s \sum A_i-B_i*ans ∑Ai−Bi∗ans,于是我们先二分出 a n s ans ans,然后我们计算1~n的 V i = A i − B i ∗ a n s V_i = A_i-B_i*ans Vi=Ai−Bi∗ans,最后取最大的k个 V i V_i Vi,求和即可。
整体二分
将询问集合二分到底层
莫队算法
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define reps(i,a,b) for(int i=a;i>=b;i--)
#define db(x) if(DEBUG) cout<<"{"<<"="<<(x)<<"}"
#define edl if(DEBUG) cout<<endl
//#define int long long
#define ll long long
using namespace std;
const bool DEBUG = 1;
const int N = 50005;
int cnt[N]={0},a[N]={0},pos[N]={0};
int n,m,ans=0;
int rd(){
int ans=0;
char p=getchar();
while(p>'9'||p<'0') p=getchar();
while(p>='0'&&p<='9') ans=ans*10+p-'0',p=getchar();
return ans;
}
struct que{
int l,r,id;
} qu[N];
bool cmp(que a,que b){
//printf("{%d %d %d}",a.id,a.l,a.r);
if(pos[a.l]==pos[b.l])
return a.r<b.r;
return pos[a.l]<pos[b.l];
}
void update(int x,int v){
ans-=cnt[a[x]]*cnt[a[x]];
cnt[a[x]]+=v;
ans+=cnt[a[x]]*cnt[a[x]];
}
ll gcd(ll m,ll n){
while(n!=0){
ll t=m%n;
m=n;
n=t;
}
return m;
}
ll u[N],v[N];
int main(){
cin>>n>>m;
int q1,q2,pl=1,pr=0;
int bk=ceil(sqrt(1.0*n));
rep(i,1,n) a[i]=rd(),pos[i]=(i-1)/bk;//,cout<<","<<pos[i]<<",";
rep(i,1,m){
q1=rd(),q2=rd();
qu[i]=(que){q1,q2,i};
}
sort(qu+1,qu+1+m,cmp);
rep(i,1,m){
int id=qu[i].id;
if(qu[i].l==qu[i].r) {
u[id]=0,v[id]=1;
continue;
}
if(pr<qu[i].r)
rep(j,pr+1,qu[i].r)
update(j,1);
else reps(j,pr,qu[i].r+1)
update(j,-1);
pr=qu[i].r;
if(pl<qu[i].l)
rep(j,pl,qu[i].l-1)
update(j,-1);
else reps(j,pl-1,qu[i].l)
update(j,1);
pl=qu[i].l;
ll aa=ans-qu[i].r+qu[i].l-1;
ll bb=(ll)(qu[i].r-qu[i].l+1)*(qu[i].r-qu[i].l);
ll cc=gcd(aa,bb);
aa/=cc,bb/=cc;
u[id]=aa,v[id]=bb;
}
rep(i,1,m) printf("%lld/%lld\n",u[i],v[i]);
}