简直要哭了。。你妹的。。这破题搞了老半天
题意呢 就是一开始时在连续区间内赋初值 然后有两种操作
操作1 将给定区间内的值都换成另一个值
操作2 给定区间内 如果这个位置的值比给定的值大 就把这个值换成这两个数的公约数
因为这是完成所有操作之后输出最终的结果 采取延迟更新的方法减少不必要的操作
当需要更新的时候再去更新。。
比赛的时候 没写好 没有往下更新 今天就重新加了 不是说数据水的吗 我怎么就TLE了
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=100005;
int gcd(int a,int b)
{
if(b)
return gcd(b,a%b);
return a;
}
struct node
{
int l,r;
int num;
int up;
int mx;
};
node no[maxn*4];
void build(int l,int r,int k)
{
if(l==r)
{
no[k].l=l;
no[k].r=r;
no[k].up=1;
scanf("%d",&no[k].num);
no[k].mx=no[k].num;
// cout<<k<<" "<<no[k].num<<endl;
return;
}
int mid=(l+r)/2;
no[k].l=l;
no[k].r=r;
no[k].num=0;
no[k].up=0;
build(l,mid,k*2);
build(mid+1,r,k*2+1);
no[k].mx=max(no[k*2].mx,no[k*2+1].mx);
}
void pushdown(int k)
{
if(no[k].up)
{
no[k*2].up=no[k*2+1].up=no[k].up;
no[k*2].num=no[k*2+1].num=no[k].num;
no[k].up=0;
}
}
void update1(int l,int r,int k,int n)
{
if(l<=no[k].l&&no[k].r<=r)
{
no[k].num=n;
no[k].up=1;
return;
}
pushdown(k);
int mid=(no[k].l+no[k].r)/2;
if(r<=mid) update1(l,r,k*2,n);
else if(l>mid) update1(l,r,k*2+1,n);
else
{
update1(l,mid,k*2,n);
update1(mid+1,r,k*2+1,n);
}
}
void update2(int l,int r,int k,int n)
{
// cout<<2222222<<endl;
int mid2=(no[k].l+no[k].r)/2;
if(l<=no[k].l&&no[k].r<=r)
{
if(no[k].up==1)
{
if(no[k].num>n)
{
no[k].num=gcd(no[k].num,n);
// cout<<no[k].num<<" "<<n<<endl;
return;
}
else return;
}
else
{
if(no[k].mx<n)
return;
else
{
int mid=(no[k].l+no[k].r)/2;
update2(l,mid,k*2,n);
update2(mid+1,r,k*2+1,n);
}
}
}
pushdown(k);
int mid=(no[k].l+no[k].r)/2;
if(r<=mid) update2(l,r,k*2,n);
else if(l>mid) update2(l,r,k*2+1,n);
else
{
update2(l,mid,k*2,n);
update2(mid+1,r,k*2+1,n);
}
}
void search(int l,int r,int k)
{
if(l<=no[k].l&&no[k].r<=r)
{
if(no[k].up)
{
for(int i=no[k].l;i<=no[k].r;i++)
printf("%d ",no[k].num);
return;
}
else
{
int midd=(no[k].l+no[k].r)/2;
search(l,midd,k*2);
search(midd+1,r,k*2+1);
}
}
else
{
int mid=(no[k].l+no[k].r)/2;
if(r<=mid) search(l,r,k*2);
else if(l>mid) search(l,r,k*2+1);
else
{
search(l,mid,k*2);
search(mid+1,r,k*2+1);
}
}
}
int main()
{
//freopen("input.txt","r",stdin);
int tc;
scanf("%d",&tc);
while(tc--)
{
int n;
scanf("%d",&n);
build(1,n,1);
int m;
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
int a,b,c,d;
scanf("%d%d%d%d",&a,&b,&c,&d);
if(a==1)
{
update1(b,c,1,d);
}
else
update2(b,c,1,d);
}
search(1,n,1);
puts("");
}
return 0;
}
小澜写的代码高能。。真的挺快的。。就是没看太懂。。。哭瞎
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define LS p<<1, l, m
#define RS p<<1|1, m+1, r
const int MAXN = (int)1e5+5;
struct node {
int t, l, r, x;
node() {}
node(int t, int l, int r, int x)
: t(t), l(l), r(r), x(x) {}
}a[MAXN];
int MAX[MAXN<<2]; //着个区间最大直 max(MAX[l], MAX[r])
int last[MAXN<<2]; //这个区间的最迟1操作时间 min(last[l], last[r])
int lazy[MAXN<<2];
int id[MAXN];
int n, Q, len;
inline void pushUp(int p) {
MAX[p] = max(MAX[p<<1], MAX[p<<1|1]);
last[p] = min(last[p<<1], last[p<<1|1]);
}
inline void pushDown(int p) {
if (lazy[p]) {
last[p<<1] = last[p<<1|1] = last[p];
MAX[p<<1] = MAX[p<<1|1] = MAX[p];
lazy[p<<1] = lazy[p<<1|1] = true;
lazy[p] = false;
}
}
int gcd(int a, int b) {
if (a<b) swap(a, b);
if (b==0) return b;
int t;
while (b!=0) {
t = b;
b = a%b;
a = t;
}
return a;
}
void build(int p, int l, int r) {
lazy[p] = false;
if (l==r) {
id[l] = p;
scanf("%d", &MAX[p]);
last[p] = 0;
return ;
}
int m = (l+r)>>1;
build(LS);
build(RS);
pushUp(p);
}
void op1(int p, int l, int r, int L, int R, int x, int t) {
if (L<=l&&r<=R) {
MAX[p] = x;
last[p] = t;
lazy[p] = true;
return ;
}
pushDown(p);
int m = (l+r)>>1;
if (L<=m) op1(LS, L, R, x, t);
if (m <R) op1(RS, L, R, x, t);
pushUp(p);
}
void op2(int p, int l, int r, int L, int R, int x, int t) {
if (MAX[p]<=x || last[p]>t) return ; //
if (l==r) { //叶子节点
MAX[p] = gcd(MAX[p], x);
return ;
}
// pushDown(p);
int m = (l+r)>>1;
if (L<=m) op2(LS, L, R, x, t);
if (m <R) op2(RS, L, R, x, t);
pushUp(p);
}
void dfs(int p, int l, int r) {
if (l==r) {
// printf("%d\n", MAX[p]);
return ;
}
pushDown(p);
int m = (l+r)>>1;
dfs(LS);
dfs(RS);
}
void solve() {
len = 0;
scanf("%d", &Q);
int L, R, x, o;
for (int i = 0; i < Q; i++) {
scanf("%d%d%d%d", &o, &L, &R, &x);
if (1==o) op1(1, 1, n, L, R, x, i);
else a[len++] = node(i, L, R, x);
}
dfs(1, 1, n);
for (int i = 0; i < len; i++)
op2(1, 1, n, a[i].l, a[i].r, a[i].x, a[i].t);
for (int i = 1; i <= n; i++)
printf("%d ", MAX[id[i]]);
puts("");
// printf("%d\n", MAX[id[n]]);
}
int main() {
#ifdef Phantom01
freopen("1006.txt", "r", stdin);
#endif // Phantom01
int T;
scanf("%d", &T);
while (T--) {
scanf("%d", &n);
build(1, 1, n);
solve();
}
return 0;
}
然后找了别人的题解 借着思路又来了一发。。也是坑的不行。。唉。。
#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string.h>
#include <string>
#define eps 1e-8
#define op operator
#define MOD 10009
#define MAXN 100005
#define ls(x) (x<<1)
#define rs(x) ((x<<1)+1)
using namespace std;
struct node
{
int l,r;
int num;
bool flag;//记录子节点中的值是不是一样的
int v;
};
node no[MAXN*4];
int gcd(int a,int b)
{
if(b)
return gcd(b,a%b);
return a;
}
void pushup(int k)
{
no[k].flag=(no[ls(k)].num==no[rs(k)].num)&&(no[ls(k)].flag)&&(no[rs(k)].flag);
no[k].num=max(no[ls(k)].num,no[rs(k)].num);
// no[k].num=no[ls(k)].num;
}
void pushdown(int k)
{
if(no[k].v>=0)
{
no[ls(k)].v=no[rs(k)].v=no[k].v;
no[ls(k)].num=no[rs(k)].num=no[k].v;
no[k].v=-1;
}
}
void build(int l,int r,int k)
{
no[k].l=l;
no[k].r=r;
no[k].flag=0;
no[k].v=-1;
if(l==r)
{
int nn;
scanf("%d",&nn);
no[k].num=nn;
no[k].flag=1;
return;
}
int mid=(l+r)/2;
build(l,mid,ls(k));
build(mid+1,r,rs(k));
pushup(k);
}
void update1(int l,int r,int k,int n)
{
if(l<=no[k].l&&no[k].r<=r)
{
no[k].flag=1;
no[k].v=n;
no[k].num=n;
return;
}
pushdown(k);
int mid=(no[k].l+no[k].r)/2;
if(l<=mid) update1(l,r,ls(k),n);//这两行写的方式啊啊啊啊
if(r>mid) update1(l,r,rs(k),n);
pushup(k);
}
void update2(int l,int r,int k,int n)
{
if(no[k].flag&&no[k].num<=n) return;
if(l<=no[k].l&&no[k].r<=r&&no[k].flag)
{
no[k].num=gcd(no[k].num,n);
no[k].v=no[k].num;
return;
}
pushdown(k);
int mid=(no[k].l+no[k].r)/2;
if(l<=mid) update2(l,r,ls(k),n);//这两行写的方式啊啊啊啊
if(r>mid) update2(l,r,rs(k),n);
pushup(k);
}
int ans(int k,int pos)
{
if(no[k].l==no[k].r)
return no[k].num;
int mid=(no[k].l+no[k].r)/2;
pushdown(k);
if(pos<=mid) return ans(ls(k),pos);
else return ans(rs(k),pos);
}
int main()
{
freopen("ceshi.txt","r",stdin);
int tc;
scanf("%d",&tc);
while(tc--)
{
int n;
scanf("%d",&n);
build(1,n,1);
int q;
scanf("%d",&q);
for(int i=0; i<q; i++)
{
int a,b,c,d;
scanf("%d%d%d%d",&a,&b,&c,&d);
if(a==1)
update1(b,c,1,d);
else update2(b,c,1,d);
}
for(int i=1; i<=n; i++)
printf("%d ",ans(1,i));
puts("");
}
return 0;
}
线段树还得继续努力