1002 Breaking Down News 2020杭电多校第8场

http://acm.hdu.edu.cn/contests/contest_showproblem.php?pid=1002&cid=886

这个榜歪到天上去了,LCT过120队,这题线段树裸题过30+队

这题就是dp[i]只能从dp[i-R]---dp[i-L]这段转移过来,那么对前缀和离散化一下,把前缀和当下标维护一棵权值线段树,记录区间段最大的dp值,注意这题由于可能有重复的前缀和,所以不要unique,就是排序然后就可以让一个位置的sum[i]确定一个下标,就不用考虑重复的问题了。

然后转移的时候就分3中情况,sum[i]-sum[j]<0,=0,>0,lower_bound,upper_bound搞搞看从线段树哪个区间的最大值转移过来。

i向后移,就把i-R从权值线段树中删了,把i-L+1加进权值线段树

#include

namespace FastIO {
    const int SIZE = 1 << 16;
    char buf[SIZE], obuf[SIZE], str[60];
    int bi = SIZE, bn = SIZE, opt;
    int read(char *s) {
        while (bn) {
            for (; bi < bn && buf[bi] <= ' '; bi++);
            if (bi < bn) break;
            bn = fread(buf, 1, SIZE, stdin);
            bi = 0;
        }
        int sn = 0;
        while (bn) {
            for (; bi < bn && buf[bi] > ' '; bi++) s[sn++] = buf[bi];
            if (bi < bn) break;
            bn = fread(buf, 1, SIZE, stdin);
            bi = 0;
        }
        s[sn] = 0;
        return sn;
    }
    bool rd(int& x) {
        int n = read(str), bf;
        if (!n) return 0;
        int i = 0; if (str[i] == '-') bf = -1, i++; else bf = 1;
        for (x = 0; i < n; i++) x = x * 10 + str[i] - '0';
        if (bf < 0) x = -x;
        return 1;
    }
};
using namespace FastIO;
using namespace std;

const int maxl=2e6+10;
const int inf=2e9+10;

int n,L,R,cnt,tot;
int a[maxl],c[maxl],sum[maxl],dp[maxl];
int id[maxl];
struct ind
{
	int val,id;	
}b[maxl];
struct node
{
	int l,r,mx;
}tr[maxl<<2];

inline void build(int k,int l,int r)
{
	tr[k].l=l;tr[k].r=r;tr[k].mx=-inf;
	if(l==r)
		return;
	int mid=(l+r)>>1;
	build(k<<1,l,mid);
	build(k<<1|1,mid+1,r);
}

inline bool cmp(const ind &a,const ind &b)
{
	return a.val>1;
	if(l<=mid)
		upd(k<<1,l,x);
	else 
		upd(k<<1|1,l,x);
	tr[k].mx=max(tr[k<<1].mx,tr[k<<1|1].mx);
}

inline int qry(int k,int l,int r)
{
	if(tr[k].l==l && tr[k].r==r)
		return tr[k].mx;
	int mid=(tr[k].l+tr[k].r)>>1;
	if(r<=mid)
		return qry(k<<1,l,r);
	else if(l>mid)
		return qry(k<<1|1,l,r);
	else
		return max(qry(k<<1,l,mid),qry(k<<1|1,mid+1,r));
}

inline void mainwork()
{
	int hd=0,tl=-1,l,r;
	dp[0]=0;
	for(int i=1;i<=n;i++)
	{
		dp[i]=-inf+1;
		if(hd1)
			dp[i]=max(dp[i],qry(1,1,l-1)+1);
	}
}

inline void print()
{
	printf("%d\n",dp[n]);
}

int main()
{
	int t;
	//scanf("%d",&t);
	rd(t);
	for(int i=1;i<=t;i++)
	{
		prework();
		mainwork();
		print();
	}
	return 0;
}

 

你可能感兴趣的:(线段树)