题目大意:n个数字,两种查询,第一种单点修改,第二种把小于x的变成x。
题目思路:
有两种做法,题目被打的tags是数据结构,但是拿几个昨晚过了的线段树代码拿来试了试T在了test 32. 后几组是后来加上的。
只介绍模拟的做法吧。
记录一个数字的单点修改,如果随后有更大的二操作,那么这个一操作就没用了,所以我们可以一操作直接赋值,二操作记录是什么时候进行的操作,并且记录操作的数值,然后我们倒着走一遍这个数组取后缀的最大值,pos[i]的意思就是在第i次操作之后进行的最大的二操作数值是多少。
然后我们遍历数组的时候,如果修改的这个当前位置的pos值比a【i】大,那么结果就是这个数,如果不是就输出a【i】。
模拟做法:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int MAXN = 2e5+5;
int a[MAXN];
int pos[MAXN];
int ch[MAXN];
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
int q;
cin>>q;
for(int i=1;i<=q;i++){
int op;
cin>>op;
if(op==1){
int x,p;
cin>>p>>x;
ch[p]=i;
a[p]=x;
}
else {
int x;
cin>>x;
pos[i]=x;
}
}
for(int i=q-1;i>=0;i--){
pos[i]=max(pos[i],pos[i+1]);
}
for(int i=1;i<=n;i++){
if(pos[ch[i]]>a[i])cout<<pos[ch[i]]<<" ";
else cout<<a[i]<<" ";
}
}
线段树做法(TLE on test 32):
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int MAXN = 2e5+5;
struct node
{
int l,r,Min,Max,flag;
}C[MAXN*4];
int a[MAXN];
inline bool scan_d(int &num)
{
char in;bool IsN=false;
in=getchar();
if(in==EOF) return false;
while(in!='-'&&(in<'0'||in>'9')) in=getchar();
if(in=='-'){ IsN=true;num=0;}
else num=in-'0';
while(in=getchar(),in>='0'&&in<='9'){
num*=10,num+=in-'0';
}
if(IsN) num=-num;
return true;
}
void build(int p,int l,int r)
{
C[p].l=l;C[p].r=r;C[p].flag=-1;
if(l==r){
C[p].Min=C[p].Max=a[l];
return ;
}
int mid=(l+r)/2;
build(2*p,l,mid);
build(2*p+1,mid+1,r);
C[p].Min=min(C[2*p].Min,C[2*p+1].Min);
C[p].Max=max(C[2*p].Max,C[2*p+1].Max);
}
void down(int p)
{
if(C[p].flag!=-1){
C[2*p].flag=C[2*p+1].flag=C[p].flag;
C[2*p].Min=C[2*p+1].Min=C[p].flag;
C[2*p].Max=C[2*p+1].Max=C[p].flag;
C[p].flag=-1;
}
}
void change(int p,int l,int r,int k)
{
if(l<=C[p].l&&C[p].r<=r){
C[p].Min=C[p].Max=k;
return;
}
down(p);
int mid=(C[p].l+C[p].r)/2;
if(l<=mid)change(2*p,l,r,k);
if(r>mid)change(2*p+1,l,r,k);
C[p].Min=min(C[2*p].Min,C[2*p+1].Min);
C[p].Max=max(C[2*p].Max,C[2*p+1].Max);
}
void change2(int p,int x)
{
if(C[p].l==C[p].r){
C[p].Min=C[p].Max=max(C[p].Max,x);
return ;
}
if(C[p].Max<=x){
C[p].Max=C[p].Min=x;
C[p].flag=x;
return ;
}
if(C[p].Min>=x){
return ;
}
down(p);
change2(2*p,x);change2(2*p+1,x);
C[p].Min=min(C[2*p].Min,C[2*p+1].Min);
C[p].Max=max(C[2*p].Max,C[2*p+1].Max);
}
int ask(int p,int l,int r)
{
if(l<=C[p].l&&C[p].r<=r){
return C[p].Min;
}
down(p);
int mid=(C[p].l+C[p].r)/2;
if(l<=mid)return ask(2*p,l,r);
if(r>mid)return ask(2*p+1,l,r);
}
void dfs(int x)
{
if(C[x].l==C[x].r){
printf("%d ",C[x].Max);
return ;
}
down(x);
dfs(2*x);
dfs(2*x+1);
}
int main()
{
int n;
// scanf("%d",&n);
scan_d(n);
for(int i=1;i<=n;i++){
//scanf("%d",&a[i]);
scan_d(a[i]);
}
build(1,1,n);
int q;
//scanf("%d",&q);
scan_d(q);
while(q--)
{
int op;
//scanf("%d",&op);
scan_d(op);
if(op==1){
int p,x;
//scanf("%d%d",&p,&x);
scan_d(p);scan_d(x);
change(1,p,p,x);
}
else {
int x;
//scanf("%d",&x);
scan_d(x);
change2(1,x);
}
}
dfs(1);
printf("\n");
}