https://cn.vjudge.net/contest/234556#problem/R
题意:
就是找某几个弧线在某一段的最大值
分析:暴力
代码:
#include<bits/stdc++.h>
#define ll unsigned long long
#define inf 1e9+7
using namespace std;
struct node
{
double p,x,y;
double h,a,b;
}d[50005];
double v[50005];
void solve(int i)
{
d[i].h=d[i].y;
double s;
d[i].b=-d[i].x;
s=(d[i].p+d[i].b)*(d[i].p+d[i].b);
d[i].a=-1.0*(d[i].h/s);
}
int main()
{
int i,j,n,m;
double l,r;
int t,tt;
while(~scanf("%d",&n)){
for(i=1;i<=n;i++)
{
scanf("%lf%lf%lf",&d[i].p,&d[i].x,&d[i].y);
solve(i);
}
scanf("%d",&m);
int k=0;
while(m--)
{
k++;
v[k]=0;
scanf("%d%d%lf%lf",&t,&tt,&l,&r);
for(i=t;i<=tt;i++)
{
if(-d[i].b>=l&&-d[i].b<=r){
v[k]=max(v[k],d[i].y);
continue;
}
v[k]=max(v[k],d[i].a*(l+d[i].b)*(l+d[i].b)+d[i].h);
v[k]=max(v[k],d[i].a*(r+d[i].b)*(r+d[i].b)+d[i].h);
}
printf("%.6f\n",v[k]);
}
}
}
https://cn.vjudge.net/contest/234556#problem/J
题意:
求某一个直线经过的点,和域的个数
分析:
线段树区间查询更新
代码:
#include<bits/stdc++.h>
#define ll unsigned long long
#define inf 1e9+7
using namespace std;
int a[100005],b[100005],f[100005],num[100005];
struct node
{
int sum;
int sign;
}v[2][100005<<2];
int findset(int v)
{
if(f[v]==-1)return v;
return findset(f[v]);
}
void build(int k,int l,int r)
{
if(l==r)
{
v[0][k].sum=v[1][k].sum=v[0][k].sign=v[1][k].sign=0;
}
else
{
int mid;
mid=(l+r)>>1;
build((k<<1),l,mid);
build((k<<1)+1,mid+1,r);
v[0][k].sum=v[1][k].sum=v[0][k].sign=v[1][k].sign=0;
}
}
void down(int id,int k,int l,int r)
{
if(v[id][k].sign!=0)
{
v[id][(k<<1)].sign+=v[id][k].sign;
v[id][(k<<1)+1].sign+=v[id][k].sign;
int mid;
mid=(l+r)>>1;
v[id][(k<<1)].sum+=(mid-l+1)*v[id][k].sign;
v[id][(k<<1)+1].sum+=(r-mid)*v[id][k].sign;
v[id][k].sign=0;
}
}
void up(int id,int k,int l,int r)
{
v[id][k].sum+=v[id][(k<<1)].sum+v[id][(k<<1)+1].sum;
}
void update(int id,int k,int l,int r,int ls,int rs,int val)
{
if(ls<=l&&rs>=r)
{
v[id][k].sum+=(r-l+1)*val;
v[id][k].sign+=val;
return;
}
int mid;
mid=(l+r)>>1;
down(id,k,l,r);
if(ls<=mid)
update(id,(k<<1),l,mid,ls,rs,val);
if(rs>mid)
update(id,(k<<1)+1,mid+1,r,ls,rs,val);
up(id,k,l,r);
}
int get(int id,int k,int l,int r,int ls,int rs)
{
if(ls<=l&&rs>=r)
{
return v[id][k].sum;
}
int mid;
mid=(l+r)>>1;
down(id,k,l,r);
int ans;
ans=0;
if(ls<=mid)
ans+=get(id,(k<<1),l,mid,ls,rs);
if(rs>mid)
ans+=get(id,(k<<1)+1,mid+1,r,ls,rs);
up(id,k,l,r);
return ans;
}
int main()
{
int i,j,t,n,m;
string s;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
memset(f,-1,sizeof(f));
int maxn=0;
for(i=0;i<n;i++)
{
int aa,bb;
scanf("%d%d",&aa,&bb);
a[i]=bb*2;
b[i]=bb*2;
num[i]=1;
maxn=max(maxn,bb);
}
maxn=maxn*2;
build(1,0,maxn);
scanf("%d",&m);
while(m--)
{
cin>>s;
if(s[0]=='r')
{
int aa,bb;
scanf("%d%d",&aa,&bb);
int x,y;
x=findset(aa);
y=findset(bb);
if(x!=y)
{
if(num[x]>1)update(0,1,0,maxn,a[x],b[x],-1);
if(num[x]>1)update(1,1,0,maxn,a[x],b[x],-num[x]);
if(num[y]>1)update(0,1,0,maxn,a[y],b[y],-1);
if(num[y]>1)update(1,1,0,maxn,a[y],b[y],-num[y]);
f[x]=y;
num[y]=num[y]+num[x];
a[y]=min(a[y],a[x]);
b[y]=max(b[y],b[x]);
update(0,1,0,maxn,a[y],b[y],1);
update(1,1,0,maxn,a[y],b[y],num[y]);
}
}
else
{
double h;
scanf("%lf",&h);
int aa;
aa=int(h);
aa=aa*2+1;
//printf("ssss %d\n",aa);
if(aa>maxn)
printf("0 0\n");
else
printf("%d %d\n",get(0,1,0,maxn,aa,aa),get(1,1,0,maxn,aa,aa));
}
}
}
}
https://cn.vjudge.net/contest/234556#problem/H
题意:
这个题题意很简单,但是看不出来是线段树的题,就是求第几个数
分析:
线段树区间求和
代码:
#include<bits/stdc++.h>
#define ll unsigned long long
#define inf 1e9+7
using namespace std;
int a[200005],m;
struct node
{
int sum;
}v[200005<<2];
void build(int k,int l,int r)
{
int mid;
if(l==r)
{
v[k].sum=1;
}
else
{
mid=(l+r)>>1;
build((k<<1),l,mid);
build((k<<1)+1,mid+1,r);
v[k].sum=v[(k<<1)].sum+v[(k<<1)+1].sum;
}
}
void update(int k,int l,int r,int pos,int val)
{
if(l==r)
{
v[k].sum=val;
}
else
{
int mid;
mid=(l+r)>>1;
if(pos<=mid)
update((k<<1),l,mid,pos,val);
else
update((k<<1)+1,mid+1,r,pos,val);
v[k].sum=v[(k<<1)].sum+v[(k<<1)+1].sum;
}
}
int get(int k,int l,int r,int ls,int rs)
{
if(rs<ls)return 0;
if(ls<=l&&rs>=r)
return v[k].sum;
else
{
int mid;
mid=(l+r)>>1;
int ans;
ans=0;
if(ls<=mid)
ans+=get((k<<1),l,mid,ls,rs);
if(rs>mid)
ans+=get((k<<1)+1,mid+1,r,ls,rs);
return ans;
}
}
int main()
{
int m,i,j,n,t;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
build(1,1,n);
for(i=0;i<n;i++)
{
int x;
scanf("%d",&x);
int l,r,mid;
l=1;
r=n;
int ant;
ant=x+1;
while(l<r)
{
mid=(l+r)>>1;
if(get(1,1,n,1,mid)<ant)l=mid+1;
else
r=mid;
}
if(i)printf(" ");
printf("%d",r);
update(1,1,n,r,0);
}
printf("\n");
}
}
题意:1~n按从上到下排列,m次询问,每次问x之前的有多少个数字,并且将x放到队首
思路:线段树更新和求和
代码:
#include<bits/stdc++.h>
#define ll unsigned long long
#define inf 1e9+7
using namespace std;
int a[200005],m;
struct node
{
int sum;
}v[200005<<2];
void build(int k,int l,int r)
{
int mid;
if(l==r)
{
if(l<=m)
v[k].sum=0;
else
v[k].sum=1;
}
else
{
mid=(l+r)>>1;
build((k<<1),l,mid);
build((k<<1)+1,mid+1,r);
v[k].sum=v[(k<<1)].sum+v[(k<<1)+1].sum;
}
}
void update(int k,int l,int r,int pos,int val)
{
if(l==r)
{
v[k].sum=val;
}
else
{
int mid;
mid=(l+r)>>1;
if(pos<=mid)
update((k<<1),l,mid,pos,val);
else
update((k<<1)+1,mid+1,r,pos,val);
v[k].sum=v[(k<<1)].sum+v[(k<<1)+1].sum;
}
}
int get(int k,int l,int r,int ls,int rs)
{
if(rs<ls)return 0;
if(ls<=l&&rs>=r)
return v[k].sum;
else
{
int mid;
mid=(l+r)>>1;
int ans;
ans=0;
if(ls<=mid)
ans+=get((k<<1),l,mid,ls,rs);
if(rs>mid)
ans+=get((k<<1)+1,mid+1,r,ls,rs);
return ans;
}
}
int main()
{
int n,i,j,aa,bb,k,t;
int tt;
k=0;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
n+=m;
build(1,1,n);
tt=m;
memset(a,0,sizeof(a));
for(i=0;i<m;i++)
{
if(i)printf(" ");
int x;
scanf("%d",&x);
int aa;
if(a[x]==0)
aa=x+m;
else
aa=a[x];
printf("%d",get(1,1,n,1,aa-1));
update(1,1,n,aa,0);
update(1,1,n,tt,1);
a[x]=tt;
tt--;
}
printf("\n");
}
}