The mook jong
问题描述
ZJiaQ为了强身健体,决定通过木人桩练习武术。ZJiaQ希望把木人桩摆在自家的那个由1*1的地砖铺成的1*n的院子里。由于ZJiaQ是个强迫症,所以他要把一个木人桩正好摆在一个地砖上,由于木人桩手比较长,所以两个木人桩之间地砖必须大于等于两个,现在ZJiaQ想知道在至少摆放一个木人桩的情况下,有多少种摆法。
输入描述
输入有多组数据,每组数据第一行为一个整数n(1 < = n < = 60)
输出描述
对于每组数据输出一行表示摆放方案数
输入样例
1
2
3
4
5
6
输出样例
1
2
3
5
8
12
思路:dp[i][0]表示第i个格子不放的情况,dp[i][1]表示第i个格子放的情况
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
typedef long long LL;
const int maxn=100010;
const int maxm=1010;
const int MOD=1e9+7;
const int INF=0x3f3f3f3f;
LL dp[maxn][2];
int N;
int main()
{
while(scanf("%d",&N)!=EOF)
{
memset(dp,0,sizeof(dp));
dp[0][0]=1;
dp[1][1]=dp[2][1]=dp[3][1]=1;
for(int i=1;i<=N;i++)
{
dp[i][0]=dp[i-1][0]+dp[i-1][1];
if(i>3)dp[i][1]=dp[i-3][0]+dp[i-3][1];
}
printf("%I64d\n",dp[N][0]+dp[N][1]-1);
}
return 0;
}
digger
问题描述
地主小花有n座山,这些山在地主家门前排成一条直线。这些山一开始均有相同的高度。 每一天,小花都会要求ZJiaQ开挖机把几座山挖掉一定高度,或者给一些山堆上一些高度。并且要求报告ZJiaQ报告现在有多少座山属于“高山脉”
当一排山的高度相等,并且比这排山左边和右边的山要高时,这排山被称为高山脉。
当然,最左边和最右边的山不可能是“高山脉”的一部分
输入描述
输入有多组数据
每组数据第一行有3个整数n,q,r(1<=n<=10^9,1<=q<=50000,0<=r<=1000)
接下来的q行,每行有3个整数l,r,val(1<=l<=r<=n,-1000<=val<=1000),表示从第l座山到第r座山的高度变更了val。每次输入的l,r,val需要与前一次的答案进行异或操作得到的值才是真正的l,r,val。第一次输入的l,r,val不需要。
输出描述
输出q行,每行一个数字表示答案
输入样例
5 5 0
4 5 87
2 5 -48
3 3 17
4 5 -171
5 5 -494
输出样例
0
0
0
1
1
思路:线段树维护,因为N非常大,所以用动态线段树,具体见代码
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
typedef long long LL;
const int maxn=50010;
const int maxm=1010;
const int MOD=1e9+7;
const int INF=0x3f3f3f3f;
int N,Q;
int root,cur;
struct Node
{
int sum; //共有多少高山脉
int ch[2];//左右孩子编号
int rsum,lsum;//从左边起、从右边起高度相同的连续的有多少个
int lh,rh;//左边连续、右边连续的高度
int ll,rr;//左边第一个不连续的,右边第一个不连续的高度
int add;
void init(int l,int r)
{
add=sum=lh=rh=ll=rr=ch[0]=ch[1]=0;
lsum=rsum=r-l+1;
}
};
struct IntervalTree
{
Node node[maxn*60];
void check(int & o,int l,int r)
{
if(o)return;
o=++cur;
node[o].init(l,r);
if(l==1)node[o].ll=INF;
if(r==N)node[o].rr=INF;
}
void maintain(int o,int val)
{
node[o].add+=val;
node[o].rr+=val;
node[o].ll+=val;
node[o].lh+=val;
node[o].rh+=val;
}
void pushdown(int o,int l,int r)
{
if(node[o].add)
{
int mid=(l+r)>>1;
check(node[o].ch[0],l,mid);
check(node[o].ch[1],mid+1,r);
maintain(node[o].ch[0],node[o].add);
maintain(node[o].ch[1],node[o].add);
node[o].add=0;
}
}
void pushup(int o,int l,int r)
{
int mid=(l+r)>>1;
check(node[o].ch[0],l,mid);
check(node[o].ch[1],mid+1,r);
int lson=node[o].ch[0],rson=node[o].ch[1];
node[o].sum=node[lson].sum+node[rson].sum;
node[o].lsum=node[lson].lsum;node[o].rsum=node[rson].rsum;
node[o].lh=node[lson].lh;node[o].rh=node[rson].rh;
node[o].ll=node[lson].ll;node[o].rr=node[rson].rr;
if(node[lson].rh==node[rson].lh)
{
if(node[lson].rh>node[lson].rr&&node[rson].lh>node[rson].ll)
node[o].sum+=node[lson].rsum+node[rson].lsum;
if(node[lson].rsum==mid-l+1)
{
node[o].lsum+=node[rson].lsum;
node[o].ll=node[rson].ll;
}
if(node[rson].lsum==r-mid)
{
node[o].rsum+=node[lson].rsum;
node[o].rr=node[lson].rr;
}
}
else
{
if(node[lson].lsum==mid-l+1)node[o].ll=node[rson].lh;
if(node[lson].rh>node[rson].lh&&node[lson].rh>node[lson].rr)
node[o].sum+=node[lson].rsum;
if(node[rson].rsum==r-mid)node[o].rr=node[lson].rh;
if(node[rson].lh>node[lson].rh&&node[rson].lh>node[rson].ll)
node[o].sum+=node[rson].lsum;
}
}
void update(int &o,int l,int r,int q1,int q2,int x)
{
check(o,l,r);
if(q1<=l&&r<=q2)
{
maintain(o,x);
return ;
}
pushdown(o,l,r);
int mid=(l+r)>>1;
if(q1<=mid)update(node[o].ch[0],l,mid,q1,q2,x);
if(q2>mid)update(node[o].ch[1],mid+1,r,q1,q2,x);
pushup(o,l,r);
}
}tree;
void solve()
{
root=cur=0;
int ans=0;
int l,r,val;
for(int i=0;i<Q;i++)
{
scanf("%d%d%d",&l,&r,&val);
l^=ans,r^=ans,val^=ans;
if(l>r)swap(l,r);
tree.update(root,1,N,l,r,val);
ans=tree.node[1].sum;
printf("%d\n",ans);
}
}
int main()
{
while(scanf("%d%d%*d",&N,&Q)!=EOF)
solve();
return 0;
}