http://acm.hdu.edu.cn/contests/contest_show.php?cid=803
打的惨不忍睹,就过了3题
1004:水题,直接输出Yes就过了, solved by lyy
#include
using namespace std;
#define ll long long
int n;
int main()
{
while (~scanf("%d",&n))
{
printf("Yes\n");
}
return 0;
}
1010:逆序对*min(x,y) ,队友一开始WA了4发,给了他模板都不肯抄,偷懒随便上网找了两个逆序对的模板恰巧都是错的,GG finally solved by lyy
#include
using namespace std;
#define ll long long
ll cnt;
int n;
int a[500005],t[500005];
int x,y;
void merge_sort(int *A,int x,int y,int *T)
{
if (y-x>1)
{
int m=x+(y-x)/2;
int p=x,q=m,i=x;
merge_sort(A,x,m,T);
merge_sort(A,m,y,T);
while (p=y || (p
1007 维护两个线段数即可,第一个是进位,一开始存的是,维护区间最小值,每次区间减一,如果为0,就需要进位,对应第二个线段树更新;第二个存的是答案,最终输出答案即可,一开始以为会炸,在极端情况下有可能到O(n^2),但是直接AC了
#include
using namespace std;
#define ll long long
#define maxn 100005
int b[100005];
int n,m;
namespace lyy
{
//线段树模板
ll sum[maxn<<2],add[maxn<<2];//sum求和,add为懒惰标记
int a[maxn];//存原数组数据下标[1,n]
//pushup函数更新节点信息 ,这里是求和
void pushup(int rt)
{
sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
//Build函数建树
void build(int l,int r,int rt)
{
if(l==r) //若到达叶节点
{
sum[rt]=a[l];//储存数组值
return;
}
int m=(l+r)>>1;
//左右递归
build(l,m,rt<<1);
build(m+1,r,rt<<1|1);
//更新信息
pushup(rt);
}
void update(int L,int c,int l,int r,int rt)
{
if(l==r) //到叶节点,修改
{
sum[rt]+=c;
return;
}
int m=(l+r)>>1;
//根据条件判断往左子树调用还是往右
if (L<=m) update(L,c,l,m,rt<<1);
else update(L,c,m+1,r,rt<<1|1);
pushup(rt);//子节点更新了,所以本节点也需要更新信息
}
void pushdown(int rt,int ln,int rn)
{
//ln,rn为左子树,右子树的数字数量。
if(add[rt])
{
//下推标记
add[rt<<1]+=add[rt];
add[rt<<1|1]+=add[rt];
//修改子节点的sum使之与对应的Add相对应
sum[rt<<1]+=add[rt]*ln;
sum[rt<<1|1]+=add[rt]*rn;
//清除本节点标记
add[rt]=0;
}
}
void update(int L,int R,int c,int l,int r,int rt)
{
if(L<=l && r<=R)//如果本区间完全在操作区间[L,R]以内
{
sum[rt]+=c*(r-l+1);//更新数字和,向上保持正确
add[rt]+=c;
//增加Add标记,表示本区间的sum正确,子区间的sum仍需要根据Add的值来调整
return ;
}
int m=(l+r)>>1;
pushdown(rt,m-l+1,r-m);//下推标记
//这里判断左右子树跟[L,R]有无交集,有交集才递归
if (L<=m) update(L,R,c,l,m,rt<<1);
if (R>m) update(L,R,c,m+1,r,rt<<1|1);
pushup(rt);//更新本节点信息
}
ll query(int L,int R,int l,int r,int rt)
{
if(L<=l && r<=R)//在区间内,直接返回
{
return sum[rt];
}
int m=(l+r)>>1;
//下推标记,否则sum可能不正确
pushdown(rt,m-l+1,r-m);
//累计答案
ll ans=0;
if(L <= m) ans+=query(L,R,l,m,rt<<1);
if(R > m) ans+=query(L,R,m+1,r,rt<<1|1);
return ans;
}
}
int sum[maxn<<2],add[maxn<<2];//sum求和,add为懒惰标记
int a[maxn];//存原数组数据下标[1,n]
//pushup函数更新节点信息 ,这里是求和
void pushup(int rt)
{
sum[rt]=min(sum[rt<<1],sum[rt<<1|1]);
}
//Build函数建树
void build(int l,int r,int rt)
{
if(l==r)
{
sum[rt]=a[l];
return;
}
int m=(l+r)>>1;
build(l,m,rt<<1);
build(m+1,r,rt<<1|1);
pushup(rt);
}
void pushdown(int rt)
{
if(add[rt])
{
add[rt<<1]+=add[rt];
add[rt<<1|1]+=add[rt];
sum[rt<<1]+=add[rt];
sum[rt<<1|1]+=add[rt];
add[rt]=0;
}
}
void go(int l,int r,int rt)
{
if (l==r)
{
//cout<>1;
pushdown(rt);
if (l<=m && sum[rt<<1]==1) go(l,m,rt<<1);
if (r>m && sum[rt<<1|1]==1) go(m+1,r,rt<<1|1);
pushup(rt);
}
void update(int L,int R,int l,int r,int rt)
{
if(L<=l && r<=R)
{
if (sum[rt]==1)
{
go(l,r,rt);
sum[rt]-=1;
add[rt]-=1;
}
else
{
sum[rt]-=1;
add[rt]-=1;
}
return;
}
int m=(l+r)>>1;
pushdown(rt);
if (L<=m) update(L,R,l,m,rt<<1);
if (R>m) update(L,R,m+1,r,rt<<1|1);
pushup(rt);
}
int query(int L,int R,int l,int r,int rt)
{
if(L<=l && r<=R)
{
return sum[rt];
}
int m=(l+r)>>1;
pushdown(rt);
int ans=0;
if(L <= m) ans+=query(L,R,l,m,rt<<1);
if(R > m) ans+=query(L,R,m+1,r,rt<<1|1);
return ans;
}
int main()
{
while (~scanf("%d%d",&n,&m))
{
memset(lyy::a,0,sizeof(lyy::a));
memset(lyy::add,0,sizeof(lyy::add));
lyy::build(1,n,1);
for (int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
build(1,n,1);
memset(add,0,sizeof(add));
for (int i=1;i<=m;i++)
{
char c[10];
int x,y;
scanf("%s%d%d",c,&x,&y);
if (c[0]=='a') update(x,y,1,n,1);
else printf("%d\n",lyy::query(x,y,1,n,1));
}
}
return 0;
}