这道题是昨天多校联合比赛的1006题,我是用线段树(区间树)做的,这道题还可以用暴力做。
但是用线段树耗时1200ms,时间复杂度很低。而暴力至少得8000ms,
但是这道题提交了很多遍,但都是wrong ansers ,今天再重新交了一遍,之所以wrong 是因为杭电用%I64d 输入输出。而我用的是long long
坑......................
附上代码:
#include <stdio.h> #include <string.h> #include <cmath> #include <iostream> typedef long long ll; using namespace std; const int maxn=101000; struct node { int l,r,cover; // 这里的cover的值要么为0 要么为1 ,当cover==1的时候表示这个区间所有的值都相等 ll inc; //这个值的意思用于1操作和2操作时的记录,这样就不必要每次操作到叶子节点,时间复杂度能下去; }data[maxn*8]; ll a[maxn+1]; ll GCD(ll a,ll b) //最大公约数公式 { if(!b)return a; return GCD(b,a%b); } void build(int l,int r,int k) //建树的过程 { int mid; data[k].l=l; data[k].r=r; data[k].inc=0; data[k].cover=0; if (l==r) { data[k].inc=a[l]; data[k].cover=1; return ; } mid=(l+r)/2; build(l,mid,k*2); build(mid+1,r,k*2+1); } void change(int k,int l,int r,ll x) //1 操作。。。。 { int mid; if (data[k].l==l&&data[k].r==r) //找到这个区间后,把要更改的x值用inc记录,然后cover==1,表示这个区间内所有数都为x了 { data[k].inc=x; data[k].cover=1; return ; } if(data[k].cover==1) //这一步的意思是,当所要更改的区间是子区间,那么这个cover等于1就被破坏了,那么我们将这个节点的属性转移给左右节点 { data[2*k].cover=data[k].cover; data[2*k+1].cover=data[k].cover; data[2*k].inc=data[k].inc; data[2*k+1].inc=data[k].inc; data[k].cover=0; data[k].inc=0; } mid=(data[k].l+data[k].r)/2; if(r<=mid) change(2*k,l,r,x); else if (l>mid) change(2*k+1,l,r,x); else {change(2*k,l,mid,x); change(2*k+1,mid+1,r,x);} } void gcd(int k,int l,int r,ll x) //2操作 { int mid; if(data[k].l==l&&data[k].r==r&&data[k].cover==1) { if(data[k].inc>x) { data[k].inc=GCD(data[k].inc,x); data[k].cover=1; } return; } if(data[k].cover==1) //同理如果所要更改的区间是子区间,那么这个cover=1就被破坏了,所以要属性转移 { data[2*k].cover=data[k].cover; data[2*k+1].cover=data[k].cover; data[2*k].inc=data[k].inc; data[2*k+1].inc=data[k].inc; data[k].cover=0; data[k].inc=0; } mid=(data[k].l+data[k].r)/2; if (r<=mid)gcd(2*k,l,r,x); else if(l>mid)gcd(2*k+1,l,r,x); else { gcd(2*k,l,mid,x); gcd(2*k+1,mid+1,r,x); } } void sove(int k) //这个函数是用于最后输出处理的,如果某个节点的cover值等于1,那么就让这个节点以下的所有叶子节点的值都等于inc { if(data[k].cover==1) { for(int i=data[k].l;i<=data[k].r;i++)a[i]=data[k].inc; return ; } sove(2*k); sove(2*k+1); } int main() { int T,n,m,op,l,r; ll x; cin>>T; while(T--) { memset(a,0,sizeof(a)); scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%I64d",&a[i]); //以后要记住输入也得用%I64d build(1,n,1); scanf("%d",&m); while(m--) { scanf("%d%d%d%I64d",&op,&l,&r,&x); if(op==1)change(1,l,r,x); else if(op==2)gcd(1,l,r,x); } sove(1); for(int i=1;i<=n;i++) printf("%I64d ",a[i]); //输出用I64d; printf("\n"); } return 0; }