问题B:时间机器
数据这么大,是贪心了。开始想到贪心,忘了贪心过后的结果只看与后面的状态的关系就行了,然后推出许多反例,就放弃了贪心。再想想,二分图匹配?好了,又忘了看
数据范围,一直写二分图匹配,后来才发现不行。
太想AC一道题的人,可能最后A了,可能一无所有,我就是后者了。
正解是贪心,全部按左端点排序,对于每一个节点,选择电阻的策略是,电阻的左端点大于节点的右端点且电阻的右端点尽量靠近节点的左端点。如果枚举来找电阻的话,
时间复杂度O(nm),能拿70分。可以用map或者set优化,时间复杂度((n+m)logn+nlogn))
上代码。
1 #include<iostream> 2 #include<map> 3 #include<algorithm> 4 #include<cstring> 5 #define maxn 50005 6 #define LL long long 7 using namespace std; 8 map<int,LL>M; 9 int n,m,t; 10 struct Node{ 11 int l,r,k; 12 bool operator <(const Node&t) const{ 13 return l<t.l; 14 } 15 }A[maxn],R[maxn]; 16 inline void read(int &x){ 17 x=0;int f=1;char c=getchar(); 18 while(!isdigit(c)){f=c=='-'?-1:1;c=getchar();} 19 while(isdigit(c)){x=(x<<3)+(x<<1)+(c^48);c=getchar();} 20 x=x*f; 21 } 22 inline void add(int pos,int num){ 23 if(M[pos]) M[pos]+=num; 24 else M[pos]=num; 25 } 26 inline void solve(){ 27 register int j=1; 28 for(register int i=1;i<=n;i++){ 29 while(A[i].k){ 30 while(j<=m&&R[j].l<=A[i].l) add(R[j].r,R[j].k),j++; 31 map<int,LL>::iterator it=M.lower_bound(A[i].r);//上文说的贪心策略 32 if(it==M.end()){ 33 puts("No"); 34 return ; 35 } 36 else if(A[i].k<it->second) it->second-=A[i].k,A[i].k=0;//map中的排序是按照键值排序的,之前一直不知道. 37 else A[i].k-=it->second,M.erase(it); 38 } 39 } 40 puts("Yes"); 41 } 42 int main(){ 43 freopen("machine.in","r",stdin); 44 freopen("machine.out","w",stdout); 45 read(t); 46 while(t--){ 47 memset(A,0,sizeof(A)); 48 memset(R,0,sizeof(R)); 49 M.clear(); 50 read(n),read(m); 51 for(register int i=1;i<=n;i++) 52 read(A[i].l),read(A[i].r),read(A[i].k); 53 for(register int i=1;i<=m;i++) 54 read(R[i].l),read(R[i].r),read(R[i].k); 55 sort(A+1,A+1+n); 56 sort(R+1,R+1+m); 57 solve(); 58 } 59 }

浙公网安备 33010602011771号