题目:noip2012 day2
第一题 同余方程
这一题是一道扩欧的模板题(几乎不需要其他技巧)
ax=1(mode b)
即ax+by=1的解方程,但是由于较久没有接触数论,忘得差不多了,于是选择了暴力的方法,只得了60
注意一点,因为x不止一个值,也不止正值,所以需要在输出时进行一个小小的处理
第二题 借教室
这一题似乎不止一种解法,组里面有几位大佬用了线段树,本人是蒟蒻所以不记得写了(由此可见我数论图论学的有多不牢)
后面接受了一种解法---二分,因为接教室遵循先来后到的原则,所以如果第K个人可以,那么第K-1个人也一定可以,所以可以进行二分,先二分K值,里面再两重循环求值比较,但是如果不进行优化依旧会爆炸,所以可以进行预处理,用前缀和来优化,for 1~k,定义一个数组存值,将起点处加上值,结尾+1处减去该值(每次二分后数组都要清零),这样求和时只需要一重循环走一遍即可,大大减少了时间复杂度(似乎说的复杂了,还是码个代码吧)
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int n,m;
long long day[1000005],z[1000005],q[1000005],zh[1000005],tar[1000005];
int shu[100];
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",&day[i]);
for(int i=1;i<=m;i++){
cin>>zh[i]>>q[i]>>z[i];
}
int l=0,r=m+1;
while(r-l>1){
int flag=1,zz=0;
int k=r+l>>1;
for(int i=1;i<=n+1;i++) tar[i]=0;
for(int i=1;i<=k;i++) {
tar[q[i]]+=zh[i];
tar[z[i]+1]-=zh[i];
}
for(int i=1;i<=n;i++){
zz+=tar[i];
if(zz>day[i]){
flag=0;
break;
}
}
if(flag)l=k;
else r=k;
}
if(l==m)
cout<<"0";
else{
cout<<"-1"<<endl;
cout<<r;
}
return 0;
}
(代码丑是一直以来的痛处。。。)