8.8日联赛解题报告(前两题)

来源:互联网 发布:南京证券软件下载 编辑:程序博客网 时间:2024/05/22 05:22

题目: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;
}

(代码丑是一直以来的痛处。。。)

原创粉丝点击