正解给的是二分。刚做这题一看不是裸线段树吗,结果被卡了OTZ,加读入优化并卡常过的…
#include <stdio.h>
#include <ctype.h>
#define min(a,b) ((a)<(b)?(a):(b))
int n,m,room[1000001],x,y,c;
struct tree
{
int mini,lazy;
}node[4000001];
char getc()
{
static const int LEN = 1<<15;
static char buf[LEN],*S=buf,*T=buf;
if(S == T)
{
T = (S=buf)+fread(buf,1,LEN,stdin);
if(S == T)return EOF;
}
return *S++;
}
int read()
{
static char ch;
static int D;
while(!isdigit(ch=getc()));
for(D=ch-'0'; isdigit(ch=getc());)
D=(D<<3)+(D<<1)+(ch-'0');
return D;
}
void pushdown(int l,int r,int rt)
{
int tmp = node[rt].lazy;
if(!tmp) return ;
node[rt].lazy=0;
node[rt<<1].mini += tmp;
node[rt<<1|1].mini += tmp;
node[rt<<1].lazy += tmp;
node[rt<<1|1].lazy += tmp;
}
void build(int l,int r,int rt)
{
if(l==r)
{
node[rt].mini = read();
return ;
}
int mid=(l+r)>>1;
//这个写法其实不标准,如果l+r爆范围就GG了,正规写法:l+(r-l)/2
//不要在意这些细节...我是来卡常的...
build(l,mid,rt<<1);
build(mid+1,r,rt<<1|1);
node[rt].mini = min(node[rt<<1].mini, node[rt<<1|1].mini);
}
void update(int l,int r,int v,int sl,int sr,int rt)
{
if(sl==l && sr==r)
{
node[rt].lazy += v;
node[rt].mini += v;
return ;
}
int mid = (l+r)>>1;
if(node[rt].lazy) pushdown(l,r,rt);
if(sr <= mid) update(l, mid, v, sl, sr, rt<<1);
else if(sl > mid) update(mid+1, r, v, sl, sr, rt<<1|1);
else
{
update(l, mid, v, sl, mid, rt<<1);
update(mid+1, r, v, mid+1, sr, rt<<1|1);
}
node[rt].mini = min(node[rt<<1].mini, node[rt<<1|1].mini);
}
int main()
{
n=read();m=read();
build(1, n, 1);
for(int i = 1; i <= m; i++)
{
c=read();x=read();y=read();
update(1, n, -c, x, y, 1);
if(node[1].mini < 0)
{
printf("-1\n%d\n",i);
return 0;
}
}
printf("0\n");
return 0;
}