POJ 3468(線分樹+lazy思想)

4700 ワード

読み込み時に%I 64 dを使用していない結果はずっとWA..
#include <iostream>
#include <cstdio>
using namespace std;

__int64 total=0;
__int64 A[100000];

struct CNode
{
	int left,right;
	CNode *leftchild,*rightchild;
	__int64 sum;
	__int64 inc;
};

CNode* build(int l,int r)
{
	CNode* root=new CNode;
        root->left=l;
	root->right=r;
	root->sum=0;
	root->inc=0;
	root->leftchild=NULL;
	root->rightchild=NULL;
	if (l!=r)
	{
		int mid=(l+r)/2;
		root->leftchild=build(l,mid);
		root->rightchild=build(mid+1,r);
	}
	return root;
}

void add(int l,int r,int c,CNode* root)
{
	if (l<=root->left && r>=root->right)
	{
		root->inc+=c;
	}
	else
	{
		if (l>=root->left && r<=root->right)
		  root->sum+=(r-l+1)*c;
		else if (l>=root->left && r>root->right)
			root->sum+=(root->right-l+1)*c;
		else if (l<root->left && r>root->right)
			root->sum+=(root->right-root->left+1)*c;
		else
			root->sum+=(r-root->left+1)*c;
		if ( l<=(root->left+root->right)/2 ) add(l,r,c,root->leftchild);
		if ( r>(root->left+root->right)/2 ) add(l,r,c,root->rightchild);
	}
}

void getsum(int l,int r,CNode* root)
{
	if (l<=root->left && r>=root->right)
	{
		total+=root->sum;
		total+=(root->right-root->left+1)*root->inc;
	}
	else
	{
		root->sum+=(root->right-root->left+1)*root->inc;
		if (root->leftchild!=NULL)
		  root->leftchild->inc+=root->inc;
		if (root->rightchild!=NULL)
		  root->rightchild->inc+=root->inc;
		root->inc=0;
		if ( l<=(root->left+root->right)/2 ) getsum(l,r,root->leftchild);
		if ( r>(root->left+root->right)/2 ) getsum(l,r,root->rightchild);
	}
}

int main()
{
	int N,Q;
	int i;
	char ch;
	int a,b,c;
	
	scanf("%d%d",&N,&Q);
	CNode* root=build(1,N);
	scanf("%I64d",&A[0]);
	for (i=1;i<=N-1;i++)
	{
		scanf("%I64d",&A[i]);
		A[i]+=A[i-1];
	}
	getchar();
	while (Q--)
	{
		scanf("%c",&ch);
		if (ch=='Q')
		{
			scanf("%d%d",&a,&b);
			getchar();
			getsum(a,b,root);
			if (a>=2)
			  total+=A[b-1]-A[a-2];
			else
				total+=A[b-1];
			printf("%I64d
",total); total=0; } else { scanf("%d%d%d",&a,&b,&c); getchar(); add(a,b,c,root); } } return 0; }

バージョン2:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;

__int64 A[100005];
__int64 total;

struct Node
{
	int l,r;
	struct Node *lchild,*rchild;
	__int64 sum,inc;
}Root;

void build(int l,int r,struct Node *root)
{
	root->l=l;
	root->r=r;
	root->lchild=root->rchild=NULL;
	root->sum=root->inc=0;
	if (l==r)
		return;
	int mid=(l+r)/2;
	root->lchild=new struct Node;
	build(l,mid,root->lchild);
	root->rchild=new struct Node;
	build(mid+1,r,root->rchild);
}

void add(int l,int r,int inc,struct Node *root)
{
	int mid=(root->l+root->r)/2;
	if (l<=root->l && r>=root->r)
	  root->inc+=inc;
	else if (l>mid)
	{
		root->sum+=(min(r,root->r)-l+1)*inc;
		add(l,r,inc,root->rchild);
	}
	else if (r<=mid)
	{
		root->sum+=(r-max(l,root->l)+1)*inc;
		add(l,r,inc,root->lchild);
	}
	else
	{
		root->sum+=(min(r,root->r)-max(l,root->l)+1)*inc;
		add(l,r,inc,root->lchild);
		add(l,r,inc,root->rchild);
	}
}

void query(int l,int r,struct Node *root)
{
	root->sum+=(root->r-root->l+1)*root->inc;
	if (root->lchild!=NULL)
		root->lchild->inc+=root->inc;
	if (root->rchild!=NULL)
		root->rchild->inc+=root->inc;
	root->inc=0;

	int mid=(root->l+root->r)/2;
	if (l<=root->l && r>=root->r)
		total+=root->sum;
	else if (l>mid)
		query(l,r,root->rchild);
	else if (r<=mid)
		query(l,r,root->lchild);
	else
	{
		query(l,r,root->lchild);
		query(l,r,root->rchild);
	}
}

int main()
{
	int N,Q,i,a,b,c;
	char s[2];
	scanf("%d%d",&N,&Q);
	scanf("%I64d",&A[1]);
	for (i=2;i<=N;i++)
	{
		scanf("%I64d",&A[i]);
		A[i]+=A[i-1];
	}
	build(1,N,&Root);
	for (i=1;i<=Q;i++)
	{
		scanf("%s",s);
		if (s[0]=='Q')
		{
			scanf("%d%d",&a,&b);
			query(a,b,&Root);
			total+=A[b]-A[a-1];
			printf("%I64d
",total); total=0; } else { scanf("%d%d%d",&a,&b,&c); add(a,b,c,&Root); } } }