2021年集训(8.2~8.4)
这两天疫情突然来袭,烟台的形势突然紧张起来……
敌兵布阵
传送门
//https://vjudge.ppsucxtt.cn/contest/450704#problem/A
#include <stdio.h>
#include <string.h>
#define N 50005
int number[N],L[4*N],R[4*N],tree[4*N];
void Pushup(int id)
{
tree[id]=tree[2*id]+tree[2*id+1];
}
void Build(int l,int r,int id)
{
L[id]=l,R[id]=r;
if(l==r)
{
tree[id]=number[l];
return ;
}
int mid=(l+r)/2;
Build(l,mid,2*id);
Build(mid+1,r,2*id+1);
Pushup(id);
}
void Update(int n,int m,int id)
{
if(L[id]==n&&R[id]==n)
{
tree[id]+=m;
return ;
}
int mid=(L[id]+R[id])/2;
if(n<=mid)
Update(n,m,2*id);
else
Update(n,m,2*id+1);
Pushup(id);
}
int Query(int l,int r,int id)
{
if(L[id]>=l&&R[id]<=r)
return tree[id];
int ans=0;
int mid=(L[id]+R[id])/2;
if(l<=mid)
ans+=Query(l,r,2*id);
if(r>mid)
ans+=Query(l,r,2*id+1);
return ans;
}
int main()
{
int T;
scanf("%d",&T);
for(int i=1;i<=T;i++)
{
memset(L,0,sizeof(L));
memset(R,0,sizeof(R));
memset(tree,0,sizeof(tree));
printf("Case %d:\n",i);
int n;
scanf("%d",&n);
for(int j=1;j<=n;j++)
scanf("%d",&number[j]);
Build(1,n,1);
char opt[10];
while(scanf("%s",&opt)!=EOF)
{
if(strcmp(opt,"Add")==0)
{
int n,m;
scanf("%d%d",&n,&m);
Update(n,m,1);
}
if(strcmp(opt,"Sub")==0)
{
int n,m;
scanf("%d%d",&n,&m);
Update(n,-m,1);
}
if(strcmp(opt,"Query")==0)
{
int l,r;
scanf("%d%d",&l,&r);
printf("%d\n",Query(l,r,1));
}
if(strcmp(opt,"End")==0)
break;
}
}
return 0;
}
Lost Cows
传送门
//https://vjudge.ppsucxtt.cn/contest/450704#problem/B
#include <stdio.h>
#define N 8005
int number[N],ans[N],L[4*N],R[4*N],tree[4*N];
void Pushup(int id)
{
tree[id]=tree[2*id]+tree[2*id+1];
}
void Build(int l,int r,int id)
{
L[id]=l,R[id]=r;
if(l==r)
{
tree[id]=1;
return ;
}
int mid=(l+r)/2;
Build(l,mid,2*id);
Build(mid+1,r,2*id+1);
Pushup(id);
}
int Query(int n,int id)
{
tree[id]--;
if(L[id]==R[id])
return L[id];
int ans;
if(tree[2*id]>=n)
ans=Query(n,2*id);
else
ans=Query(n-tree[2*id],2*id+1);
return ans;
}
int main()
{
int n;
scanf("%d",&n);
Build(1,n,1);
for(int i=1;i<=n;i++)
{
if(i==1)
number[i]=0;
else
scanf("%d",&number[i]);
}
for(int i=n;i>=1;i--)
ans[i]=Query(number[i]+1,1);
for(int i=1;i<=n;i++)
printf("%d\n",ans[i]);
return 0;
}
Mayor’s posters(离散化)
传送门
//https://vjudge.ppsucxtt.cn/contest/450704#problem/C
//https://blog.csdn.net/CUCUC1/article/details/107370653
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define N 10005
int ans;
int left[N],right[N],number[4*N],tree[16*N],flag[N];
//left和right存原始数据,开1倍
//number存left和right中的元素,还可能有不少增补元素,所以开4倍
//tree开number的4倍也就是16倍
//flag用于记录当前颜色是否已被计算,避免出现重复计算的情况,开1倍
void Update(int L,int R,int x,int l,int r,int id)
{
if(l>=L&&r<=R)
{
tree[id]=x;
return ;
}
if(tree[id]!=-1)//相当于Pushdown,只不过没有写成单独的函数
{
tree[2*id]=tree[id];
tree[2*id+1]=tree[id];
tree[id]=-1;
}
int mid=(l+r)/2;
if(L<=mid)
Update(L,R,x,l,mid,2*id);
if(R>mid)
Update(L,R,x,mid+1,r,2*id+1);
}
void Query(int L,int R,int l,int r,int id)
{
if(l>=L&&r<=R&&tree[id]!=-1)
{
if(!flag[tree[id]])
{
ans++;
flag[tree[id]]=1;
}
return ;
}
if(l==r)
return ;
int mid=(l+r)/2;
if(L<=mid)
Query(L,R,l,mid,2*id);
if(R>mid)
Query(L,R,mid+1,r,2*id+1);
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
memset(left,0,sizeof(left));
memset(right,0,sizeof(right));
memset(number,0,sizeof(number));
memset(tree,-1,sizeof(tree));
memset(flag,0,sizeof(flag));
int n,num=1;//num为number数组中元素的实际个数加1
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d%d",&left[i],&right[i]);
number[num++]=left[i];
number[num++]=right[i];
}
sort(number+1,number+num);//去重前排序
num=unique(number+1,number+num)-number;//去重,最后减去的是number而不是number+1,保证了num为实际个数加1
int cnt=num;//cnt用于循环计数
for(int i=2;i<cnt;i++)//cnt本来就是实际个数加1,不用跑到第cnt次,只用跑到第cnt-1次
if(number[i]>number[i-1]+1)
number[num++]=number[i-1]+1;//如果相邻两元素相差大于1,则增补元素
sort(number+1,number+num);//增补后排序
for(int i=1;i<=n;i++)
{
int l=lower_bound(number+1,number+num,left[i])-number;//由于用的是lower_bound,所以最后只用减number就可以得到其在数组中的位置,而不用减number+1
int r=lower_bound(number+1,number+num,right[i])-number;//由于用的是lower_bound,所以最后只用减number就可以得到其在数组中的位置,而不用减number+1
Update(l,r,i,1,num-1,1);
}
ans=0;
Query(1,num-1,1,num-1,1);
printf("%d\n",ans);
}
return 0;
}
Just a Hook
传送门
//https://vjudge.ppsucxtt.cn/contest/450704#problem/D
#include <stdio.h>
#include <string.h>
#define N 100005
int L[4*N],R[4*N],tree[4*N],flag[4*N];
void Pushup(int id)
{
tree[id]=tree[2*id]+tree[2*id+1];
}
void Build(int l,int r,int id)
{
L[id]=l,R[id]=r;
if(l==r)
{
tree[id]=1;
return ;
}
int mid=(l+r)/2;
Build(l,mid,2*id);
Build(mid+1,r,2*id+1);
Pushup(id);
}
void Pushdown(int id,int len)
{
tree[2*id]=flag[id]*(len-len/2);
tree[2*id+1]=flag[id]*(len/2);
flag[2*id]=flag[id];
flag[2*id+1]=flag[id];
flag[id]=0;
}
void Update(int l,int r,int x,int id)
{
if(L[id]>=l&&R[id]<=r)
{
tree[id]=x*(R[id]-L[id]+1);
flag[id]=x;
return ;
}
if(flag[id])
Pushdown(id,R[id]-L[id]+1);
int mid=(L[id]+R[id])/2;
if(l<=mid)
Update(l,r,x,2*id);
if(r>mid)
Update(l,r,x,2*id+1);
Pushup(id);
}
int Query(int l,int r,int id)
{
if(L[id]>=l&&R[id]<=r)
return tree[id];
if(flag[id])
Pushdown(id,R[id]-L[id]+1);
int ans=0;
int mid=(L[id]+R[id])/2;
if(l<=mid)
ans+=Query(l,r,2*id);
if(r>mid)
ans+=Query(l,r,2*id+1);
return ans;
}
int main()
{
int T;
scanf("%d",&T);
for(int i=1;i<=T;i++)
{
memset(L,0,sizeof(L));
memset(R,0,sizeof(R));
memset(tree,0,sizeof(tree));
memset(flag,0,sizeof(flag));
int n;
scanf("%d",&n);
Build(1,n,1);
int m;
scanf("%d",&m);
while(m--)
{
int l,r,x;
scanf("%d%d%d",&l,&r,&x);
Update(l,r,x,1);
}
printf("Case %d: The total value of the hook is %d.\n",i,Query(1,n,1));
}
return 0;
}
I Hate It
传送门
//https://vjudge.ppsucxtt.cn/contest/450704#problem/E
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define N 200005
int number[N],L[4*N],R[4*N],tree[4*N];
void Pushup(int id)
{
tree[id]=max(tree[2*id],tree[2*id+1]);
}
void Build(int l,int r,int id)
{
L[id]=l,R[id]=r;
if(l==r)
{
tree[id]=number[l];
return ;
}
int mid=(l+r)/2;
Build(l,mid,2*id);
Build(mid+1,r,2*id+1);
Pushup(id);
}
void Update(int x,int y,int id)
{
if(L[id]==x&&R[id]==x)
{
tree[id]=y;
return ;
}
int mid=(L[id]+R[id])/2;
if(x<=mid)
Update(x,y,2*id);
else
Update(x,y,2*id+1);
Pushup(id);
}
int Query(int l,int r,int id)
{
if(L[id]>=l&&R[id]<=r)
return tree[id];
int ans1=0x80000000,ans2=0x80000000;
int mid=(L[id]+R[id])/2;
if(l<=mid)
ans1=Query(l,r,2*id);
if(r>mid)
ans2=Query(l,r,2*id+1);
return max(ans1,ans2);
}
int main()
{
int n,m;
while(scanf("%d%d",&n,&m)!=EOF)
{
memset(L,0,sizeof(L));
memset(R,0,sizeof(R));
memset(tree,0,sizeof(tree));
for(int i=1;i<=n;i++)
scanf("%d",&number[i]);
Build(1,n,1);
while(m--)
{
char opt;
getchar();
scanf("%c",&opt);
if(opt=='U')
{
int x,y;
scanf("%d%d",&x,&y);
Update(x,y,1);
}
if(opt=='Q')
{
int l,r;
scanf("%d%d",&l,&r);
printf("%d\n",Query(l,r,1));
}
}
}
return 0;
}
Ultra-QuickSort
传送门
//https://vjudge.ppsucxtt.cn/contest/450704#problem/F
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define N 500005
int L[4*N],R[4*N],tree[4*N];
struct node
{
int n;
int id;
}number[N];
bool cmp(node x,node y)
{
if(x.n!=y.n)
return x.n<y.n;
else
return x.id<y.id;
}
void Pushup(int id)
{
tree[id]=tree[2*id]+tree[2*id+1];
}
void Build(int l,int r,int id)
{
L[id]=l,R[id]=r;
if(l==r)
return ;
int mid=(l+r)/2;
Build(l,mid,2*id);
Build(mid+1,r,2*id+1);
}
void Update(int n,int id)
{
if(L[id]==R[id])
{
tree[id]++;
return ;
}
int mid=(L[id]+R[id])/2;
if(n<=mid)
Update(n,2*id);
else
Update(n,2*id+1);
Pushup(id);
}
int Query(int l,int r,int id)
{
if(L[id]>=l&&R[id]<=r)
return tree[id];
int ans=0;
int mid=(L[id]+R[id])/2;
if(l<=mid)
ans+=Query(l,r,2*id);
if(r>mid)
ans+=Query(l,r,2*id+1);
return ans;
}
int main()
{
int n;
while(scanf("%d",&n)!=EOF&&n)
{
memset(L,0,sizeof(L));
memset(R,0,sizeof(R));
memset(tree,0,sizeof(tree));
Build(1,n,1);
for(int i=1;i<=n;i++)
{
scanf("%d",&number[i].n);
number[i].id=i;
}
sort(number+1,number+1+n,cmp);
long long ans=0;
for(int i=1;i<=n;i++)
{
ans+=Query(number[i].id+1,n,1);//???
Update(number[i].id,1);//???
}
printf("%lld\n",ans);
}
return 0;
}
Buy Tickets
传送门
//https://vjudge.ppsucxtt.cn/contest/450704#problem/G
#include <stdio.h>
#include <string.h>
#define N 200005
int cnt;
int pos[N],val[N],ans[N],L[4*N],R[4*N],tree[4*N],number[4*N];
void Pushup(int id)
{
tree[id]=tree[2*id]+tree[2*id+1];
}
void Build(int l,int r,int id)
{
L[id]=l,R[id]=r;
if(l==r)
{
tree[id]=1;
return ;
}
int mid=(l+r)/2;
Build(l,mid,2*id);
Build(mid+1,r,2*id+1);
Pushup(id);
}
void Update(int pos,int val,int id)
{
tree[id]--;
if(L[id]==R[id])
{
number[id]=val;
return ;
}
if(tree[2*id]>=pos)
Update(pos,val,2*id);
else
Update(pos-tree[2*id],val,2*id+1);
}
void output(int id)
{
if(L[id]==R[id])
{
ans[cnt++]=number[id];
return ;
}
output(2*id);
output(2*id+1);
}
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
memset(L,0,sizeof(L));
memset(R,0,sizeof(R));
memset(tree,0,sizeof(tree));
memset(number,0,sizeof(number));
Build(1,n,1);
for(int i=1;i<=n;i++)
scanf("%d%d",&pos[i],&val[i]);
for(int i=n;i>=1;i--)
Update(pos[i]+1,val[i],1);
cnt=1;
output(1);
for(int i=1;i<=n;i++)
{
if(i!=n)
printf("%d ",ans[i]);
else
printf("%d\n",ans[i]);
}
}
return 0;
}
Stars(树状数组)
传送门
//https://vjudge.ppsucxtt.cn/contest/450704#problem/H
#include <stdio.h>
#define N 32005
int tree[N],ans[N];
int lowbit(int x)
{
return x&-x;
}
void Update(int id)
{
for(int i=id;i<=N;i+=lowbit(i))
tree[i]++;
}
int Query(int id)
{
int sum=0;
for(int i=id;i;i-=lowbit(i))
sum+=tree[i];
return sum;
}
int main()
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
ans[Query(++x)]++;
Update(x);
}
for(int i=0;i<n;i++)
printf("%d\n",ans[i]);
return 0;
}
A Simple Problem with Integers
传送门
//https://vjudge.ppsucxtt.cn/contest/450704#problem/I
#include <stdio.h>
#define N 100005
int number[N],L[4*N],R[4*N],add[4*N];
long long tree[4*N];
void Pushup(int id)
{
tree[id]=tree[2*id]+tree[2*id+1];
}
void Build(int l,int r,int id)
{
L[id]=l,R[id]=r;
if(l==r)
{
tree[id]=(long long)number[l];
return ;
}
int mid=(l+r)/2;
Build(l,mid,2*id);
Build(mid+1,r,2*id+1);
Pushup(id);
}
void Pushdown(int id,int len)
{
tree[2*id]+=(long long)add[id]*(len-len/2);
tree[2*id+1]+=(long long)add[id]*(len/2);
add[2*id]+=add[id];
add[2*id+1]+=add[id];
add[id]=0;
}
void Update(int l,int r,int x,int id)
{
if(L[id]>=l&&R[id]<=r)
{
add[id]+=x;
tree[id]+=(long long)x*(R[id]-L[id]+1);
return ;
}
if(add[id])
Pushdown(id,R[id]-L[id]+1);
int mid=(L[id]+R[id])/2;
if(l<=mid)
Update(l,r,x,2*id);
if(r>mid)
Update(l,r,x,2*id+1);
Pushup(id);
}
long long Query(int l,int r,int id)
{
if(L[id]>=l&&R[id]<=r)
return tree[id];
if(add[id])
Pushdown(id,R[id]-L[id]+1);
long long ans=0;
int mid=(L[id]+R[id])/2;
if(l<=mid)
ans+=Query(l,r,2*id);
if(r>mid)
ans+=Query(l,r,2*id+1);
return ans;
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",&number[i]);
Build(1,n,1);
while(m--)
{
char opt;
getchar();
scanf("%c",&opt);
if(opt=='C')
{
int l,r,x;
scanf("%d%d%d",&l,&r,&x);
Update(l,r,x,1);
}
if(opt=='Q')
{
int l,r;
scanf("%d%d",&l,&r);
printf("%lld\n",Query(l,r,1));
}
}
return 0;
}