比赛的时候没仔细考虑,看了题目就直接上线段树,不出所料TLE,许久后改用树状数组,875ms过。比赛后才想起可以用扫描线的办法去做。。我问某胖他怎么做的。。。他说就是用你上次说的那方法做的。。T_T。
话说也知道了个道理。如果不是一边更新一边查询完全没必要用线段树或者树状数组。没必要。。线段树后来A了。加了读入优化900多ms。。当时比赛用了就早水过了。
放2个AC代码(都丧心病狂用了读入优化。加了能优化近600ms):
树状数组的:
#include <iostream>
#include <cstdio>
#include <string.h>
#include <string>
#include <algorithm>
#include <cmath>
using namespace std;
#define ll __int64
const int maxn=100005;
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
inline void scan_d(int &ret)
{
char c; ret=0;
while((c=getchar())<'0'||c>'9');
while(c>='0'&&c<='9') ret=ret*10+(c-'0'),c=getchar();
}
ll b[maxn],c[maxn];
int n;
void add_b(int x,int k)
{
for(int i = x; i >0; i -= i&(-i)) b[i]+=k;
}
void add_c(int x, int k)
{
for(int i = x; i <= n; i += i&(-i)) c[i] += x*k;
}
ll sum_b(int x)
{
ll s = 0;
for(int i = x; i <= n; i+= i&(-i)) s+=b[i];
return s;
}
ll sum_c(int x)
{
ll s = 0;
for(int i = x; i > 0; i -= i&(-i)) s+=c[i];
return s;
}
inline ll sum(int x)
{
if(x) return sum_b(x)*x+sum_c(x-1);
else return 0;
}
int main()
{
// freopen("1.txt","r",stdin);
int m,i,k;
while(~scanf("%d",&n)&&n)
{
// scanf("%d",&m);
scan_d(m);
memset(b,0,sizeof(b));
memset(c,0,sizeof(c));
int l,r;
for(i = 0; i < m; i++)
{
// scanf("%d%d%d",&l,&r,&k);
scan_d(l); scan_d(r); scan_d(k);
int newl = n-r+1,newr = n-l+1;
add_b(newr,k);
add_c(newr,k);
if(newl > 1)
{
add_b(newl-1,-k);
add_c(newl-1,-k);
}
}
scanf("%d",&m);
int ans = 0;
ll sum1,h;
for(i = 0; i < m; i++)
{
scanf("%I64d",&h);
scan_d(l);
sum1 = sum(n-l+1);
if(sum1 < h) ans++;
// cout<<sum1<<endl;
}
printf("%d\n",ans);
}
return 0;
}
扫描线:
#include<cstdio>
#include<ctype.h>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<vector>
#include<cstdlib>
#include<stack>
#include<cmath>
#include<queue>
#include<set>
#include<ctime>
#include<string.h>
#include<string>
using namespace std;
#define ll __int64
#define eps 1e-8
ll a[100005];
template<class T>
inline void scan_d(T &ret) {
char c; ret=0;
while((c=getchar())<'0'||c>'9');
while(c>='0'&&c<='9') ret=ret*10+(c-'0'),c=getchar();
}
int main()
{
#ifdef GLQ
freopen("1011.in","r",stdin);
// freopen("o.txt","w",stdout);
#endif // GLQ
int n,m,i;
while(~scanf("%d",&n)&&n)
{
memset(a,0,sizeof(a));
scan_d(m);
for(i = 0; i < m; i++)
{
int l,r,k;
scan_d(l);scan_d(r);scan_d(k);
// scanf("%d%d%d",&l,&r,&k);
a[l-1] -= k;
a[r] += k;
}
ll flag = 0;
for(i = n; i >= 0; i--)
{
flag += a[i];
a[i] = flag+a[i+1];
}
scan_d(m);
int ans = 0;
for(i = 0; i < m; i++)
{
ll h;int l;
scan_d(h);scan_d(l);
// scanf("%I64d%d",&h,&l);
if(h > a[l]) ans++;
}
printf("%d\n",ans);
}
return 0;
}