看到这个题目好纠结来着,一时间不知道从何下手。
题目要求进行两种操作:1,将区间的值全部进行替换为x;2把区间内大于x的数变为gcd(num[i],x);
当然没看题目时限,以为会被卡时间..然后用成段更新去完成操作1,然后写到操作2的函数想到如果某个区间所有值都一样的话只需要进行一次操作就OK了。
题目要求是15秒...学长没用线段树暴力就过了,膜拜大神!
#include<stdio.h> #include<string.h> #include<stdlib.h> struct node { int l,r,x,cover;//x基本没什么用处..可以用cover代替 }data[400050]; int gcd(int a,int b) { return b==0?a:gcd(b,a%b); } void build(int l,int r,int k) { data[k].l=l; data[k].r=r; data[k].cover=-1; if(l==r) { scanf("%d",&data[k].x); data[k].cover=data[k].x; return ; } int mid=(l+r)/2; build(l,mid,k*2); build(mid+1,r,k*2+1); } void updata(int l,int r,int x,int k) { if(data[k].l==l&&data[k].r==r) { data[k].cover=x; return ; } if(data[k].l==data[k].r)//可以直接把这里的data[k].x替换为cover { data[k].x=x; return ; } int mid=(data[k].l+data[k].r)/2; if(data[k].cover!=-1) { updata(data[k].l,mid,data[k].cover,k*2); updata(mid+1,data[k].r,data[k].cover,k*2+1); data[k].cover=-1; } if(r<=mid) updata(l,r,x,k*2); else if(l>mid) updata(l,r,x,k*2+1); else { updata(l,mid,x,k*2); updata(mid+1,r,x,k*2+1); } } void change(int l,int r,int x,int k) { if(data[k].cover!=-1) { if(data[k].cover<x) return ; int gy=gcd(data[k].cover,x); updata(l,r,gy,k); return ; } int mid=(data[k].l+data[k].r)/2; if(r<=mid) change(l,r,x,k*2); else if(l>mid) change(l,r,x,k*2+1); else { change(l,mid,x,k*2); change(mid+1,r,x,k*2+1); } } void print(int k) { if(data[k].cover!=-1)//如果某一段都一样直接就输出这段的值 { for(int i=data[k].l;i<=data[k].r;i++) printf("%d ",data[k].cover); return ; } print(k*2); print(k*2+1); } int main() { int n,q,t,i; scanf("%d",&t); while(t--) { scanf("%d",&n); build(1,n,1); scanf("%d",&q); while(q--) { int a,b,c,x; scanf("%d %d %d %d",&x,&a,&b,&c); if(x==1) updata(a,b,c,1); else change(a,b,c,1); } print(1); printf("\n"); } return 0; }