2019.10.9 题解报告

目录

  • 2019.10.9 题解报告
    • 时间安排:
    • 答题情况:
    • 题目解析:
    • 代码实现:

2019.10.9 题解报告

又是没有题解的 一次考试= =

时间安排:

  • T1: 9:50~11:00 T2: 9:00~9:45 T3: 8:20~9:00

    • T1 神题不可写, 先去看T3, 发现一种通过建图实现的 的 70分思路,
      暴力敲完去看T2
    • T2 仔细瞅了一眼觉得是个zz题 , 调和级数一搞复杂度就很低,
      考场上写了 线段树 , 被卡到40, 换了st表 变成80
    • 最后搞T1 , 一开始没思路决定手推样例打表 ,
      手玩多组数据后发现了规律

答题情况:

  • T1: 70 T2:40 T3:0

题目解析:

T1:

可以发现 , 每次加水时 加的水量,
在保证过多导致不平衡的情况下 越多越优

对于第一次 加入的 水数 , 不能过多导致 数量=l时 不平衡,
则可以发现 , 第一次最优添加 l/2(整除) 的水

则对于 第二次添水 , 也要维持平衡 ,
则最多 添加 l - (l/2)(整除) 的水

之后 每次添水 , 都应该向水量较少的 杯子中添加
并且 为了保持 两水杯平衡 ,
一次最多添加 2 的水

则可以得到规律


T2:

80%数据:

  1. 根据调和级数,
    枚举序列的 所有子序列, 复杂度较低

  2. 题目所求子序列长度 >=d , 枚举子序列时 从 d+1开始枚举即可
  3. 对每一个 长度为d的 区间,求和
    维护每一个 长度>d 的区间内, 最大的 长度为d的 区间的和
    可以使用线段树 或st表

    由于 题目要求 静态区间最值 , 所以st表更优
    对于线段树 因为不需要进行修改,所以只需要建树,查询即可

  4. 可以快乐枚举 长度>d 的序列,
    其最优的和 = 序列和 - 最大的 长度为d的 区间的和


T3:

大毒瘤数据结构
图上建线段树 再在线段树上修改并统计信息


代码实现:

T1:

  • 考场代码:
//
/*
By:Luckyblock
*/
#include
#include
#define int long long
//=============================================================
int l,r;
//=============================================================
inline int read()
{
    int s=1, w=0; char ch=getchar();
    for(; !isdigit(ch);ch=getchar()) if(ch=='-') s =-1;
    for(; isdigit(ch);ch=getchar()) w = w*10+ch-'0';
    return s*w;
}
//=============================================================
signed main()
{
    freopen("lock.in","r",stdin);
    freopen("lock.out","w",stdout);
    l = read(), r = read();
    if(l == r) {printf("%d",(l==1||l==2)?1:2); return 0;}
    printf("%lld",(r-l-2)/2+2);
    /*
    if(l<=1 && r<=1) {printf("0"); return 0;}
    if(l<=2 && r<=2) {printf("1"); return 0;}
    if(l == r) {printf("2"); return 0;}
    ans[1][3] = 2;
    ans[1][4] = 2;
    ans[1][5] = 3;
    
    ans[2][3] = 2;
    ans[2][4] = 2;
    ans[2][5] = 2;
    
    ans[3][4] = 1;
    ans[3][5] = 1;
    
    ans[4][5] = 1;
    
    printf("%d",ans[l][r]);
    /*
    double l1 = l*1.0, l2 = l1, r1 = r*1.0, r2 = r1;//l2,r2剩余 
    double le = 0, ri = 0;
    
    le += (l1+1)/2, r2 -= (l1+1)/2, l2 -= (l1+1)/2; 
    if(le - 1 <= 0) {printf("1"); return 0;}
    
    if(le - 1 )
    */
}
  • 正解:
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
//#pragma GCC optimize(2)
#define int long long
#define MAXN 1000000
#define INF 1e9 + 7

using namespace std;

inline int read()
{
    int x = 0, f = 1; char c = getchar();
    while(c > '9' || c < '0'){ if (c == '-') f = -1; c = getchar(); }
    while(c >= '0' && c <= '9'){ x = x * 10 + (c ^ 48); c = getchar(); }
    return f * x;
}

signed main()
{
    freopen("lock.in", "r", stdin);
    freopen("lock.out", "w", stdout);
    int l = read(), r = read();
    if (r <= 1) puts("0");
    else if (r <= 2) puts("1");
    else if (r == l) puts("2");
    else
    {
        if (r - l <= 1) r++;
        if (l == 0) r--;
        cout << (r - l) / 2 + 1;
    }
    return 0;
}

T2:

  • 考场代码:
#include
#include
#include
#define max(a,b) (a>b?a:b)
#define int long long
const int MARX = 1e6+10;
//=============================================================
int n,p,d,ans=d , sum[MARX]; 
int MAX[MARX][20];
int lg[MARX];
//=============================================================
inline int read()
{
    int s=1, w=0; char ch=getchar();
    for(; !isdigit(ch);ch=getchar()) if(ch=='-') s =-1;
    for(; isdigit(ch);ch=getchar()) w = w*10+ch-'0';
    return s*w;
}
void build()
{
/*
    for(int i=1;i<=MARX;i++)//预处理log函数 
      lg[i]=lg[i-1]+(1<
  • 正解:
#include
#define ll long long
#define pb push_back
#define mk make_pair
#define rint register int
using namespace std;
inline ll read(){ll w=1,s=0;char ch=getchar();while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();}while(isdigit(ch)){s=s*10+ch-'0';ch=getchar();}return w*s;}
ll Sum[2000010];
ll tmp[2000010];
ll Max[2000010],pos[2000100];
int A[2000010];
ll n,p,d;
int main()
{
    freopen("sequence.in","r",stdin);
    freopen("sequence.out","w",stdout);
    n=read(),p=read(),d=read();
    for(rint i=1;i<=n;++i)
    {
        A[i]=read();Sum[i]=Sum[i-1]+A[i];
    }
    for(rint i=1;i<=d-1;++i) tmp[i]=Sum[i];
    for(rint i=d;i<=n;++i)
    {
        tmp[i]=Sum[i]-Sum[i-d];
    }
//  if(n<=d)
//  {
//      cout<Max[tail]) tail--;
                    Max[++tail]=tmp[rp];
                    pos[tail]=rp;
                }
            }
            else
            {   ll tt=-1e18;
                if(head<=tail) tt=max(tt,Max[head]);
                tt=max(tt,tmp[rp+1]);
                if(Sum[rp+1]-Sum[l-1]-tt<=p)
                {
                    rp++;
                    while(head<=tail&&tmp[rp]>Max[tail]) tail--;
                    Max[++tail]=tmp[rp];
                    pos[tail]=rp;
                }
                else break;
            }
        }
        ans=max(ans,rp-l+1);
    }cout<

T3:

  • 考场代码:
//
/*
By:Luckyblock
*/
#include
#include
#include
#define int long long
const int MARX = 1e5+10;
const int INF = 2e9+7;
//=============================================================
struct edge
{
    int u,v,ne;
    bool use;
}e[MARX<<2];
int n,k,num,ans , w[MARX],head[MARX];
//=============================================================
inline int read()
{
    int s=1, w=0; char ch=getchar();
    for(; !isdigit(ch);ch=getchar()) if(ch=='-') s =-1;
    for(; isdigit(ch);ch=getchar()) w = w*10+ch-'0';
    return s*w;
}
void add(int u,int v)//建图 
{
    e[++num].u = u, e[num].v = v;
    e[num].ne = head[u], head[u] = num;
}
int lower_search(int value)//找到小于 value的最后一个位置 
{
    int pos;
    for(int l=0,r=n+1; l<=r;)
    {
      int mid = (l+r) >> 1;
      if(w[mid] >= value)  r = mid-1;
      else pos = mid,l = mid+1;
    }
    return pos;
}
int upper_search(int value)//找到大于value的第一个位置 
{
    int pos;
    for(int l=0,r=n+1; l<=r;)
    {
      int mid = (l+r) >> 1;
      if(w[mid] > value)  pos = mid,r = mid-1;
      else l = mid+1;
    }
    return pos;
}
//=============================================================
signed main()
{
    freopen("fight.in","r",stdin);
    freopen("fight.out","w",stdout);
    n = read(), k = read(); w[n+1] = INF; 
    if(k == 0) {printf("0"); return 0;}
    for(int i=1; i<=n; i++) w[i] = read();  
    std:: sort(w+1, w+n+1);
    
    for(int i=n; i>=1; i--)
      for(int j = 1; w[j] < w[i]; j++)
       {
         add(i,j); e[num].use = 1;
         add(j,i);
       }
        
    while(k--)
    {
      int l = read(), r = read();
      int le = lower_search(l)+1, ri = upper_search(r)-1;
      for(int i=le; i<=ri; i++)
        for(int j=head[i]; j; j=e[j].ne)
          if(e[j].use == 1)
            if(e[j].v >= le && e[j].v <= ri)
              e[j].use = 0, e[(j%2?j+1:j-1)].use=1;
    }
    for(int u=1; u<=n; u++)
    {
      for(int i=head[u]; i; i=e[i].ne)
        if(e[i].use && e[i].v > u)
          for(int j=head[e[i].v]; j; j=e[j].ne)
            if(e[j].use && e[j].v > e[j].u)
              for(int k=head[e[j].v]; k; k=e[k].ne)
                if(e[k].use && e[k].v == u) 
                  ans++;
    }
    printf("%lld",ans);
}
/*
4 0
1 1 1 2
*/
  • 正解:
#include
#define ll long long
#define pb push_back
#define mk make_pair
#define rint register int
//#define int ll
using namespace std;
inline int read(){int w=1,s=0;char ch=getchar();while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();}while(isdigit(ch)){s=s*10+ch-'0';ch=getchar();}return w*s;}
typedef pair pa;
vector vec[200010];
int n,m;ll A[500010];
ll tot=0,q[500010];
ll Sum[500010],tag[500010],du[500100];
inline void pushdown(int now,int l,int r)
{
    if(tag[now])
    {   int mid=(l+r)>>1;
        tag[now<<1]^=1;
        tag[now<<1|1]^=1;
        Sum[now<<1]=(mid-l+1)-Sum[now<<1];
        Sum[now<<1|1]=(r-mid)-Sum[now<<1|1];
        tag[now]=0;
    }
}
inline void Modify(int now,int l,int r,int x,int y)
{
//  cout<>1;
    if(x<=mid) Modify(now<<1,l,mid,x,y);
    if(y>mid) Modify(now<<1|1,mid+1,r,x,y);
    Sum[now]=Sum[now<<1]+Sum[now<<1|1];
}
inline ll Query(int now,int l,int r,int x,int y)
{   if(x>y) return 0;
    if(x<=l&&r<=y)
    {
        return Sum[now];
    }pushdown(now,l,r);
    int mid=(l+r)>>1;
    ll res=0;
    if(x<=mid) res=Query(now<<1,l,mid,x,y);
    if(y>mid) res+=Query(now<<1|1,mid+1,r,x,y);
    Sum[now]=Sum[now<<1]+Sum[now<<1|1];
    return res;
}
inline void Solve()
{
    for(rint i=1;i<=n;++i)
    {
        if(i!=1)
        {
            Modify(1,1,n,i-1,i-1);
        }
        int sz=vec[i].size();
        for(rint j=0;j=y) continue;
        vec[x].pb(mk(x,y));
        vec[y+1].pb(mk(x,y));
    }
    Solve();
    return 0;
}

你可能感兴趣的:(2019.10.9 题解报告)