链接:https://vjudge.net/contest/304079
B
#include <bits/stdc++.h>
using namespace std;
long long gcd(long long a,long long b)
{
return b?gcd(b,a%b):a;
}
vector<long long>v[1000005];
long long sum[1000005];
int a[1000005];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
scanf("%d",&a[i]);
}
long long x,y,maxn=0;
for(int i=1;i<=n;i++)
{
scanf("%lld%lld",&x,&y);
v[y].push_back(x);
sum[i]=0;
}
sum[n+1]=0;
for(int i=1;i<=m;i++)
{
sort(v[i].begin(),v[i].end(),greater<long long >());
}
for(int i=1;i<=m;i++)
{
maxn=max(maxn,(long long)v[i].size());
for(int j=1;j<v[i].size();j++)
{
if(j<a[i])
{
v[i][j]+=v[i][j-1];
v[i][j-1]=0;
}
sum[j]+=v[i][j-1];
}
if(v[i].size()&&v[i].size()>=a[i])
sum[v[i].size()]+=v[i][v[i].size()-1];
v[i].clear();
}
double maxx=0;
long long maxi=1;
for(int i=1;i<=maxn;i++)
{
if(maxx<(sum[i]*1.0)/(i*1.0))
{
maxx=(sum[i]*1.0)/(i*1.0);
maxi=i;
}
sum[i+1]+=sum[i];
}
printf("%lld/%lld\n",sum[maxi]/gcd(sum[maxi],maxi),maxi/gcd(maxi,sum[maxi]));
}
return 0;
}
H
#include <bits/stdc++.h>
using namespace std;
long long a[1000005];
long long b[1000005];
long long c[1000005];
long long tc[1000005*4];
long long tb[1000005*4];
void update1(int i,int l,int r,int x,long long t)
{
if(l==r)
{
tb[i]=t;
return;
}
int mid=l+r>>1;
if(x<=mid)
update1(i*2,l,mid,x,t);
else
update1(i*2+1,mid+1,r,x,t);
tb[i]=tb[i*2]+tb[i*2+1];
}
long long query1(int i,int l,int r,int x,int y)
{
if(l>=x&&r<=y)
{
return tb[i];
}
int mid=l+r>>1;
long long sum=0;
if(x<=mid)
sum+=query1(i*2,l,mid,x,y);
if(y>mid)
sum+=query1(i*2+1,mid+1,r,x,y);
return sum;
}
void update2(int i,int l,int r,int x,long long t)
{
if(l==r)
{
tc[i]=t;
return;
}
int mid=l+r>>1;
if(x<=mid)
update2(i*2,l,mid,x,t);
else
update2(i*2+1,mid+1,r,x,t);
tc[i]=tc[i*2]+tc[i*2+1];
}
long long query2(int i,int l,int r,int x,int y)
{
if(l>=x&&r<=y)
{
return tc[i];
}
int mid=l+r>>1;
long long sum=0;
if(x<=mid)
sum+=query2(i*2,l,mid,x,y);
if(y>mid)
sum+=query2(i*2+1,mid+1,r,x,y);
return sum;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
memset(tb,0,sizeof(tb));
memset(tc,0,sizeof(tc));
int n,m;
scanf("%d%d",&n,&m);
a[0]=0;
for(int i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
b[i]=c[i]=a[i]-a[i-1];
update1(1,1,n,i,b[i]);
if(b[i]<0)
c[i]=0;
update2(1,1,n,i,c[i]);
}//op等于2处理x到y需要加的次数,首先处理这个区间x必须要首先处理,也就意味着如果x比x+1大那么x+1就会被x连带着处理掉,因此需要维护一个a[i]-a[i-1],表示这个关系,如果b[i]<0,说明不用求这个值,所以维护一个数组c,c[i]=b[i](b[i]>0);
//op等于2时求a[l]+c[l+1]+...c[r],由于对于a[i]无法维护区间修改,因此可以用b表示a[l]=(b[1]+...b[l])
//这样op等于1时只需要修改b与c的两个端点就可以完成所需目的
while(m--)
{
int op,x,y;
long long z;
scanf("%d",&op);
if(op==1)
{
scanf("%d%d%lld\n",&x,&y,&z);
b[x]+=z;
b[y+1]-=z;
c[x]=b[x];
c[y+1]=b[y+1];
if(b[y+1]<0)
c[y+1]=0;
if(b[x]<0)
c[x]=0;
update1(1,1,n,x,b[x]);
if(y+1<=n)
update1(1,1,n,y+1,b[y+1]);
update2(1,1,n,x,c[x]);
if(y+1<=n)
update2(1,1,n,y+1,c[y+1]);
}
else
{
scanf("%d%d",&x,&y);
if(x!=y)
printf("%lld\n",query1(1,1,n,1,x)+query2(1,1,n,x+1,y));
else
printf("%lld\n",query1(1,1,n,1,x));
}
}
}
return 0;
}
D 虚树问题(待补)