AK(线段树/分块)

AK
【问题描述】
NOIPOIPOIP考场上 ,马里奥 顺利地切掉了前两题,他只要再最后一就可以 AK 了。最后一题是这样的:给你个数字序列, 每次查询段区间和了。最后一题是这样的:给你个数字序列, 每次查询段区间和了。最后一题是这样的:给你个数字序列, 每次查询段区间和了。最后一题是这样的:给你个数字序列, 每次查询段区间和了。最后一题是这样的:给你个数字序列, 每次查询段区间和了。最后一题是这样的:给你个数字序列, 每次查询段区间和并且把它们都变成原来的平方。马里奥瞬间就切掉了这道题,但他觉得对 并且把它们都变成原来的平方。马里奥瞬间就切掉了这道题,但他觉得对 并且把它们都变成原来的平方。马里奥瞬间就切掉了这道题,但他觉得对 于别人来说太难了。出题在和马里奥商量后,决定询问时只要求返回模 于别人来说太难了。出题在和马里奥商量后,决定询问时只要求返回模 于别人来说太难了。出题在和马里奥商量后,决定询问时只要求返回模 一个 数 c = 2305843008676823040 的结果。作为另一名NOIP选手的你也已经切掉了 选手的你也已经切掉了 前两题,你能够解决这个修改后的问顺利 AK 吗?
【输入格式】
第一行 两个整数 n,m ,表示 数字 个数 和询问个数 。
接下来 一行 n个数字 ai ,表示 序列的 初始值。
接下 来 m行,每两个整数 l,r 表示询问区间 。
【输出格式】
对于每次询问,你需要输出一个整数表示应的结果。

这题线段树啊分块都行
主要是模数上做了手脚,就是说当一个数平方六十次左右的时候就会开始循环了(1000000以内只要28次),所以……又是优化暴力。

线段树

#include <bits/stdc++.h>
#define lson(x) (x<<1)
#define rson(x) ((x<<1)|1)
using namespace std;
typedef unsigned long long ll;
const ll mod =2305843008676823040uLL; 
const int maxn=100500;

int n,m;
ll ans,val[maxn];

struct tree{
    int left,right,flag;
    ll val;
}tree[maxn<<2];
inline ll mul(ll x,ll y)
{
    ll res=0;
    while(y){
        if(y&1) res=(res+x)%mod;
        y>>=1;
        x=x*2%mod;
    }
    return res;
}
inline void build(int left,int right,int cur)
{
    tree[cur].left=left;
    tree[cur].right=right;
    tree[cur].flag=0;
    if(left==right)
    {
        tree[cur].val=val[left];
        return;
    }
    int mid=(left+right)>>1;
    build(left,mid,(cur<<1));
    build(mid+1,right,(cur<<1)|1);
    tree[cur].val=tree[(cur<<1)].val+tree[((cur<<1)|1)].val;
}

inline void query(int a,int b,int cur)
{
    int left=tree[cur].left;
    int right=tree[cur].right;
    if(a==left && b==right && tree[cur].flag==1) { 
        ans=(ans+tree[cur].val)%mod;
        return ;
    }
    if(left==right)
    {
        ans=(ans+tree[cur].val)%mod;
        ll tmp=mul(tree[cur].val,tree[cur].val);
        if(tmp==tree[cur].val){ 
            tree[cur].flag=1;
        }
        tree[cur].val=tmp;
        return ;
    }
    int mid=(left+right)>>1;
    if(b<=mid) query(a,b,(cur<<1));
    else if(a>mid) query(a,b,((cur<<1)|1));
    else {
        query(a,mid,(cur<<1));
        query(mid+1,b,((cur<<1)|1));
    }
    tree[cur].val=(tree[(cur<<1)].val+tree[((cur<<1)|1)].val)%mod;
    if(tree[cur<<1].flag && tree[(cur<<1)|1].flag ) tree[cur].flag=1;
}

int main()
{
	//freopen("ak.in","r",stdin);
	//freopen("ak.out","w",stdout); 
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        scanf("%I64u",&val[i]);
    build(1,n,1);
    for(int i=0;i<m;i++) 
	  {
        int a,b;
        scanf("%d%d",&a,&b);
        ans=0;
        query(a,b,1);
        ans%=mod;
        printf("%I64u\n",ans);
      }
    return 0;
}

分块

# include <bits/stdc++.h>
# define int long long
# define Rint register long long 
using namespace std;
const int mo=2305843008676823040,E=30,MAXN=(2<<16)+1;
int n,m,bl;
int f[MAXN],L[MAXN],R[MAXN],sum[MAXN],cnt[MAXN];
struct rec{
	int bl,val;
}a[MAXN];
inline int read()
{
    int X=0,w=0; char c=0;
    while(c<'0'||c>'9') {w|=c=='-';c=getchar();}
    while(c>='0'&&c<='9') X=(X<<3)+(X<<1)+(c^48),c=getchar();
    return w?-X:X;
}
inline void print(Rint x)
{
    if(x>9) print(x/10);
    putchar(x%10+'0');
}
inline int father(Rint x)
{
	if (f[x]==x) return f[x];
	f[x]=father(f[x]);
	return f[x]; 
}
inline int mul(Rint a,Rint b)
{
	int res=0ll;
	while (b) {
		if (b&1) res=(res+a)%mo;
		a=(a<<1)%mo; b>>=1;
	}
	return res%mo;
}
inline int solve(Rint l,Rint r)
{
	int lb=a[l].bl,rb=a[r].bl,ans=0ll;
	if (lb==rb) {
		for (Rint i=l;i<=r;i++) 
		 ans=(ans+a[i].val)%mo;
		return ans;
	}
	for (Rint i=l;i<=R[lb];i++) ans=(ans+a[i].val)%mo;
	for (Rint i=r;i>=L[rb];i--) ans=(ans+a[i].val)%mo;
	for (Rint i=lb+1;i<=rb-1;i++) ans=(ans+sum[i])%mo; 
	return ans%mo;
}
inline void update(Rint l,Rint r)
{
	for (Rint i=l;i<=r;i=father(i+1)) {
		if (i>r||i==0) break; 
		int nowbl=a[i].bl;
		sum[nowbl]=(sum[nowbl]-a[i].val+mo)%mo;
		a[i].val=mul(a[i].val,a[i].val)%mo; cnt[i]++;
		if (cnt[i]>E) f[i]=father(i+1);
		sum[nowbl]=(sum[nowbl]+a[i].val)%mo;
	}
}
signed main()
{
	freopen("ak.in","r",stdin);
	freopen("ak.out","w",stdout);
	scanf("%lld%lld",&n,&m); 
	for (Rint i=1;i<=n;i++) f[i]=i;
	memset(cnt,0,sizeof(cnt));
	bl=1; L[1]=1;
	int POA=sqrt(n)+1;
	for (Rint i=1;i<=n;i++)  {
	   if (i%POA==0) { R[bl]=i-1; bl++; L[bl]=i; }
		a[i].val=read();
		a[i].bl=bl;
		sum[bl]=(sum[bl]+a[i].val)%mo;
	} 
	R[bl]=n;
	Rint l,r; 
	while (m--)  {
		l=read();r=read();
		print(solve(l,r)); putchar('\n');
		update(l,r);
	} 
	return 0;
}

猜你喜欢

转载自blog.csdn.net/beautiful_CXW/article/details/82944709