一看不想别的,,,,就是线段树了啊(非说是二分也可以毕竟是一样的.....)
然后就悲剧了,,,因为我不太会..记得以前做过一道ZOJ的区间更新颜色的题....但是把....忘了
于是重新找题做一下先
HDU1698 just a hook
dota!!!!哈哈.......题意很简单了
主要是打出来个模板
#include <iostream>
#include <cstdio>
#include <bits/stdc++.h>
using namespace std;
const int MAXN =
100010;
int sum[MAXN<<2];
int lazy[MAXN<<2];
void pushup(int rt)
{
sum[rt] = sum[rt<<1] + sum[rt<<1|1]; //gengxinhe,,ba zishu de jiashanglai
}
void pushdown(int rt, int x)//最大的那一块的最右边开始
{
if(lazy[rt] != -1)
{
lazy[rt<<1] = lazy[rt<<1|1] = lazy[rt];//标记值下放
sum[rt<<1] = (x-(x>>1))*lazy[rt];//左子树加上标记值
sum[rt<<1|1] = (x>>1)*lazy[rt];//右子树
lazy[rt] = -1;
}
}
void creat(int l, int r, int rt)
{
lazy[rt] = -1, sum[rt] = 1;//chushihuasuoyoujiedian sum genjutiyi shi -1
if(l == r) return;
int mid = (l+r)>>1;
creat(l, mid, rt<<1);//jian zuoyou zishu
creat(mid+1, r, rt<<1|1);
pushup(rt);
}
void modify(int l, int r, int x, int L, int R, int rt)
{
if(l <= L && r >= R) //ruguo yaogengxinde ba nage fugaile ,nage jiuzhijie jiashang nayiduan dehe jiuhao
{
lazy[rt] = x;
sum[rt] = x*(R-L+1);
return;
}
pushdown(rt, R-L+1);//jiedianbiaoji xiangxiachuanti
int mid = (L+R)>>1;
if(l <= mid) modify(l, r, x, L, mid, rt<<1); //如果在左子树有重合那就去
if(r > mid) modify(l, r, x, mid+1, R, rt<<1|1);//如果在右子树
pushup(rt); //gengxin sum
}
int main()
{
int i, j, k = 0;
int n, T, q;
int x, y, w;
while(scanf("%d", &T) != EOF)
while(T--)
{
scanf("%d %d", &n, &q);
creat(1, n, 1); //jianshu
while(q--)
{
scanf("%d %d %d", &x, &y, &w);
modify(x, y, w, 1, n, 1); //jiushi update
}
printf("Case %d: The total value of the hook is %d.\n", ++k, sum[1]);
}
return 0;
}
效率不仅在于二分更在于不是一条指令就执行一次而是加一起来执行
zoj 1610 color ~成段更新
#include<iostream>
#include<cstdio>
#include<cstring>
#define mem(str,x) memset(str,(x),sizeof(str))
#define FOR(i,s,t) for(int i=(s); i<(t); ++i)
#define FF(i,n) for(int i=0; i<(n); ++i)
#define mid ((left+right)>>1)
#define len (right-left+1)
#define lson rt<<1, left, m
#define rson rt<<1|1, m+1, right
#define STOP puts("Stop Here~");
using namespace std;
const int MAXN = 8005;
int n,col[MAXN<<2],vis[MAXN<<2],ans[MAXN<<2];
inline void push_down(int rt){
if(col[rt] != -1){
col[rt<<1] = col[rt<<1|1] = col[rt];
col[rt] = -1;
}
}
void update(int rt,int left,int right,int l,int r,int data){
if(l<=left && right<=r){
col[rt] = data;
return;
}
if(col[rt] == data) return;
if(col[rt]!=-1)push_down(rt);
int m = mid;
if(l <= m)update(lson,l,r,data);
if(r > m)update(rson,l,r,data);
}
void query(int rt,int left,int right){
if(col[rt]>=0){
for(int i=left; i<=right; ++i)
vis[i] = col[rt];
return;
}
if(left!=right && col[rt] == -1){
int m = mid;
query(lson);
query(rson);
}
}
int main(){
int a,b,c;
while(~scanf("%d",&n)){
memset(col,-1,sizeof(col));
for(int i=0; i<n; ++i){
scanf("%d%d%d",&a,&b,&c);
if(a>=b)continue;
update(1,1,8000,a+1,b,c);
}
mem(vis,-1);
query(1,1,8000);
int i = 1;
mem(ans,0);
while(i<MAXN){
int color=vis[i], j=i+1;
if(color==-1){++i; continue;}
while(vis[j]!=-1 && vis[j]==color && j<MAXN) ++j;
++ans[color];
i=j;
}
for(int i=0; i<MAXN; ++i)if(ans[i])
printf("%d %d\n",i,ans[i]);
puts("");
}
return 0;
}
做两题之后觉得好爽啊,,,,,,而且效率也很高,,,,,最然代码都参考了别人的但是明白了很多东西.......
所以再来几道!!! POJ3468
#include <iostream>
#include <cstdio>
#include <bits/stdc++.h>
#define N
111111
#define LL long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
LL add[N<<2];
LL sum[N<<2];
void PushUP(int rt)
{
sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
void PushDown(int rt,int m)
{
if(add[rt])
{
add[rt<<1]+=add[rt];
add[rt<<1|1]+=add[rt];
sum[rt<<1]+=(m-(m>>1))*add[rt];
sum[rt<<1|1]+=(m>>1)*add[rt];
add[rt]=0;
}
}
void Build(int l,int r,int rt)
{
add[rt]=0;
if(l==r)
{
scanf("%I64d",&sum[rt]);
return;
}
int m=(l+r)>>1;
Build(lson);
Build(rson);
PushUP(rt);
}
void Update(int L,int R,int c,int l,int r,int rt)
{
if(L<=l&&R>=r)
{
add[rt]+=c;
sum[rt]+=(LL)c*(r-l+1);
return;
}
PushDown(rt,r-l+1);
int m=(l+r)>>1;
if(L<=m)
Update(L,R,c,lson);
if(R>m)
Update(L,R,c,rson);
PushUP(rt);
}
LL Query(int L,int R,int l,int r,int rt)
{
if(L<=l&&R>=r)
return sum[rt];
PushDown(rt,r-l+1);
int m=(l+r)>>1;
LL ret=0;
if(L<=m) ret+=Query(L,R,lson);
if(R>m) ret+=Query(L,R,rson);
return ret;
}
int main()
{
int m,n;
scanf("%d%d",&n,&m);
Build(1,n,1);
while(m--)
{
char s[5];
int a,b,c;
scanf("%s",s);
if(s[0]=='Q')
{
scanf("%d%d",&a,&b);
printf("%I64d\n",Query(a,b,1,n,1));
}
else
{
scanf("%d%d%d",&a,&b,&c);
Update(a,b,c,1,n,1);
}
}
return 0;
}
恩....还需要再练几题的线段树,,,,,先做URAL的这个吧.......别的以后再说把.......
/*这题二分暴力可以过...*/
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
#include<bits/stdc++.h>
#include <string.h>
#define rson m+1,r,n<<1|1
const int N=1e5;
int s[N<<2];
{
if(~s[n])
{
s[n<<1]=s[n<<1|1]=s[n];
s[n]=-1;
}
}
{
if(l==r)
{
s[n]=0;
return ;
}
s[n]=-1;
int m=(l+r)>>1;
build(lson);
build(rson);
}
{
if(L==l&&R==r)
{
s[n]=c;
return ;
}
pushdown(n);
int m=(l+r)>>1;
if(R<=m) update(L,R,c,lson);
else if(L>m) update(L,R,c,rson);
else update(L,m,c,lson),update(m+1,R,c,rson);
}
{
if(l==r) return s[n];
pushdown(n);
int m=(l+r)>>1;
if(pos<=m) return query(pos,lson);
else return query(pos,rson);
}
int X[N];
struct op
{
int L,R;
char col[3];
}o[N];
{
int n;
while(~scanf("%d",&n))
{
int cnt=0;
for(int i=1;i<=n;i++)
{
scanf("%d%d%1s",&o[i].L,&o[i].R,o[i].col);
X[++cnt]=o[i].L<<1;
X[++cnt]=o[i].L<<1|1;
X[++cnt]=o[i].R<<1;
X[++cnt]=o[i].R<<1|1;
}
X[++cnt]=0;
X[++cnt]=1;
X[++cnt]=2e9;
X[++cnt]=2e9+1;
sort(X+1,X+1+cnt);
int k=1;
for(int i=2;i<=cnt;i++)
{
if(X[i]!=X[i-1]) X[++k]=X[i];
}
build(1,k,1);
for(int i=1;i<=n;i++)
{
int L=lower_bound(X+1,X+1+k,o[i].L<<1|1)-X;
int R=lower_bound(X+1,X+1+k,o[i].R<<1)-X;
int c=o[i].col[0]=='w'?0:1;
update(L,R,c,1,k,1);
}
pair<int,int>ans;
int aaa=0;
for(int i=1;i<=k;i++)
{
if(query(i,1,k,1)==1) continue;
int j=i;
while(j<=k&&query(j,1,k,1)==0) ++j;
int now=(X[j-1]>>1)-(X[i-1]>>1);
if(now>aaa)
{
aaa=now;
ans=make_pair(X[j-1]>>1,X[i-1]>>1);
}
i=j;
}
printf("%d %d\n",ans.second,ans.first);
}
return 0;
}