传送门
这题其实就是标签覆盖的问题,我目前只会线段树上进行标签覆盖,后续学到再进行补充。
对于>号:
1.一个非负整数x会让绝对值大于x的所有元素都变成负数。
2.负数x会让绝对值大于等于x的所有元素都变成负数,并且让绝对值小于x的所有元素都取相反值。
对于<号也是同样的逻辑。
考虑用线段树进行维护。
标签1表明该绝对值对应的元素都取负数形式。
标签2表明该绝对值对应的元素都取正数形式。
标签3表明该绝对值对应的元素都取相反数形式。
标签0表明该绝对值对应的元素都取原值。
1,2标签直接赋值,3进行^操作可以让1变成2,2变成1,3变成0,0变成3.
以上转换符合数学逻辑因此可以用。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define MAXN 200005
int n,q;
#define ls (root*2)
#define rs (root*2+1)
#define tmid ((tree[root].l+tree[root].r)/2)
ll a[MAXN];
struct tree{
int l;
int r;
ll lazy;
}tree[4*MAXN];
void build(int root,int l,int r)
{
tree[root].l=l;
tree[root].r=r;
if(l==r)
return ;
int mid=(l+r)/2;
build(ls,l,mid);
build(rs,mid+1,r);
}
void pushdown(int root)
{
if(tree[root].lazy==0)return;
if(tree[root].lazy==3){
tree[rs].lazy^=3;
tree[ls].lazy^=3;
} else
tree[ls].lazy=tree[rs].lazy=tree[root].lazy;
tree[root].lazy=0;
}
void update(int root,int l,int r,int cmd)
{
if(l>r)return ;
if(l==tree[root].l&&r==tree[root].r)
{
if(cmd==3)tree[root].lazy^=cmd;
else tree[root].lazy=cmd;
return ;
}
pushdown(root);
if(l<=tmid&&r>tmid)
{
update(ls,l,tmid,cmd);
update(rs,tmid+1,r,cmd);
}
else if(r<=tmid)
update(ls,l,r,cmd);
else if(l>tmid)
update(rs,l,r,cmd);
}
ll quiry(int root,int l,int r)
{
if(l==tree[root].l&&r==tree[root].r)
return tree[root].lazy;
pushdown(root);
if(l<=tmid&&r>tmid)
return quiry(ls,l,tmid)+quiry(rs,tmid+1,r);
else if(l>tmid)
return quiry(rs,l,r);
else if(r<=tmid)
return quiry(ls,l,r);
}
int main()
{
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++)
scanf("%lld",a+i);
int lim=100000;
build(1,0,lim);
while(q--)
{
char cmd;
scanf(" %c",&cmd);
int x;
scanf("%d",&x);
if(cmd=='>') {
update(1, abs(x) + 1 - (x < 0), lim, 1);
if(x<0)
update(1,1,abs(x)-1,3);
}
else {
update(1, abs(x) + 1 - (x > 0), lim, 2);
if(x>0)
update(1,1,abs(x)-1,3);
}
}
for(int i=1;i<=n;i++)
{
if(i>1)putchar(' ');
int x=quiry(1,abs(a[i]),abs(a[i]));
if(x==0)
printf("%lld",a[i]);
else if(x==2)
printf("%lld",abs(a[i]));
else if(x==1)
printf("%lld",-abs(a[i]));
else
printf("%lld",-a[i]);
}
}