列表

详情


NC26143. Master of Graph

描述

"好像有点感觉哦"--小x(Master of Graph)

每当图论大师小x看到图,他都会说一句"好像有点感觉哦",他以为自己有掌控图的能力,能把某些特定编号的点的权值修改成自己想要的值,所以每次修改后他都会自信回头(不管了),

但是他的队友(咋胡佬)发现小x并没有把那些特定编号的点的权值修改成他想要的值,由于小x给力的操作(给力哦铁汁),假设点原来的权值为x,修改后会变成f(x)(f(x)是统计十进制数字x每一位的和),

咋胡佬发现了这一规律后,自信满满地来到小x面前询问他某些特定编号的点的权值和,

您作为小x的死忠粉iXiang也发现了这一规律,自然不希望自己的idol(偶像)受到质疑,因此您决定帮助小x一一回答咋胡佬的问题

输入描述

第一行一个数字n,m(1 <= n,m <= 100000,以空格分隔),表示图的点数和边数。

第二行n个数字ai(0 <= ai <= 1000000000000,以空格分隔),表示编号为i的点的权值为ai。

接下来m行,每行两个数字(1 <= u,v <= n),代表编号u的点和编号为v的点之间的无向边

接下来一行,一个数字q(1 <= q <= 100000),表示有q个事件。

接下来q行,每行三个数字"x l r",(1 <= l <= r <= n)。

若x为1,代表小x对编号为l到r所有点的权值进行修改,您无需输出,但修改对后面的事件有影响

若x为0,代表咋胡佬对小x的询问,您需要输出编号l到r所有点的权值和

输出描述

对于每个操作0,输出编号区间[l,r]的和。

示例1

输入:

10 9
3841 45109 42780 10844 63078 15424 7341 8629 56972 10886
1 2
1 3
2 4
2 5
7 4
5 8
6 3
6 9
10 9
6
1 2 10
0 10 10
0 9 10
0 2 3
1 3 3
0 1 10

输出:

23
52
40
4012

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 139ms, 内存消耗: 7708K, 提交时间: 2019-06-08 16:02:54

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+10;
ll A[N];
ll F(ll x){
    ll ans=0;
    while(x)ans+=x%10,x/=10;
    return ans;
}
struct SegmentTree{
    int l,r,flag;ll sum;
    #define l(x) Tree[x].l
    #define r(x) Tree[x].r
    #define sum(x) Tree[x].sum
    #define flag(x) Tree[x].flag
}Tree[N*4];
void build(int p,int l,int r){
    l(p)=l;r(p)=r;
    if(l==r){sum(p)=A[l];return;}
    int mid=(l(p)+r(p))/2;
    build(p*2,l,mid);
    build(p*2+1,mid+1,r);
    sum(p)=sum(p*2)+sum(p*2+1);
}
void change(int p,int l,int r){
    if(flag(p))return;
    if(l(p)==r(p)){
        sum(p)=F(sum(p));
        if(sum(p)<10)flag(p)=1;
        return;
    }
    int mid=(l(p)+r(p))/2;
    if(l<=mid)change(p*2,l,r);
    if(r>mid)change(p*2+1,l,r);
    sum(p)=sum(p*2)+sum(p*2+1);
    flag(p)=(flag(p*2)&&flag(p*2+1));
}
ll ask(int p,int l,int r){
    if(l<=l(p)&&r>=r(p))return sum(p);
    int mid=(l(p)+r(p))/2;ll val=0;
    if(l<=mid)val+=ask(p*2,l,r);
    if(r>mid)val+=ask(p*2+1,l,r);
    return val;
}
int main(){
    int n,m,x,l,r;cin>>n>>m;
    for(int i=1;i<=n;++i)scanf("%lld",&A[i]);
    while(m--){scanf("%d%d",&x,&x);};
    build(1,1,n);
    int Q;cin>>Q;while(Q--){
        scanf("%d%d%d",&x,&l,&r);
        if(x==1)change(1,l,r);
        else printf("%lld\n",ask(1,l,r));
    }
}

C++11(clang++ 3.9) 解法, 执行用时: 234ms, 内存消耗: 12704K, 提交时间: 2019-06-09 12:50:30

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+10;
int n,m,a,u,v,q;
struct node
{
	int l,r,data,flag;
}t[N<<2];
int f(int x)
{
	int res=0;
	while(x)	res+=x%10,x/=10;
	return res;
}
void push_up(int p)
{
	t[p].data=t[p<<1].data+t[p<<1|1].data;
	t[p].flag=t[p<<1].flag+t[p<<1|1].flag;
}
void build(int p,int l,int r)
{
	t[p].l=l,t[p].r=r,t[p].flag=0;
	if(l==r)
	{
		cin>>t[p].data;return ;
	}
	int mid=l+r>>1;
	build(p<<1,l,mid);
	build(p<<1|1,mid+1,r);
	push_up(p);
}
void change(int p,int l,int r)
{
	if(t[p].r-t[p].l+1==t[p].flag)	return ;
	if(t[p].l==t[p].r)
	{
		t[p].data=f(t[p].data);
		if(t[p].data<10)	t[p].flag=1;
		return ;
	}
	int mid=t[p].l+t[p].r>>1;
	if(r<=mid)	change(p<<1,l,r);
	else if(l>mid)	change(p<<1|1,l,r);
	else	change(p<<1,l,mid),change(p<<1|1,mid+1,r);
	push_up(p);
}
int ask(int p,int l,int r)
{
	if(t[p].l==l&&t[p].r==r)	return t[p].data;
	int mid=t[p].l+t[p].r>>1;
	if(r<=mid)	return ask(p<<1,l,r);
	else if(l>mid)	return ask(p<<1|1,l,r);
	else	return ask(p<<1,l,mid)+ask(p<<1|1,mid+1,r);
}
signed main()
{
	ios::sync_with_stdio(false);
	cin>>n>>m;
	build(1,1,n);
	for(int i=1;i<=m;i++)	cin>>u>>v;
	cin>>q;
	while(q--)
	{
		int op;
		cin>>op>>u>>v;
		if(op)	change(1,u,v);
		else	cout<<ask(1,u,v)<<endl;
	}
	return 0;
}

上一题