传送门 这题其实就是标签覆盖的问题,我目前只会线段树上进行标签覆盖,后续学到再进行补充。
对于>号: 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]); } }