• 2019.2.26模拟


    T1.电灯
    题目描述不贴了。

    这题好像有很多做法。题目还是很简单的……但是自己很菜还想了好久。
    容易知道所获得的最长交错序列必然是由多个交错序列拼接的,所以只要每次枚举反转哪一个序列更新答案即可。
    intlsy的做法是首先处理出来,如果想修改成交替序列有哪些位置需要被修改,之后取其中连续段更新答案。复杂度都是(O(n))

    T2.比萨
    题目描述不贴了。

    这题比上面做法还多。有一种(O(n))的玄学做法,不会,可以问Dukelv
    尺取法的做法没太懂。
    我的做法是贪心+二分。一开始容易想到(O(n^2logn))的暴力,之后我们只要把二分判定过程中的贪心改成用(lowerbound)去找那个符合条件的点在哪就行。
    如果不合法继续枚举断点,然后二分找中间切的位置,具体实现使用前缀和维护。复杂度(O(nlog^2n))

    #include<bits/stdc++.h>
    #define rep(i,a,n) for(int i = a;i <= n;i++)
    #define per(i,n,a) for(int i = n;i >= a;i--)
    #define enter putchar('
    ')
    
    using namespace std;
    typedef long long ll;
    const int M = 400005;
    
    ll read()
    {
    	ll ans = 0,op = 1;char ch = getchar();
    	while(ch < '0' || ch > '9') {if(ch == '-') op = -1;ch = getchar();}
    	while(ch >= '0' && ch <= '9') ans = ans * 10 + ch - '0',ch = getchar();
    	return ans * op;
    }
    
    ll n,a[M],sum[M],L,R,ans;
    
    bool check(ll x)
    {
    	rep(i,1,n)
    	{
    		int k = lower_bound(sum+i,sum+n+i,x+sum[i-1])-sum;
    		int p = lower_bound(sum+k+1,sum+n+i,x+sum[k])-sum;
    		if(sum[n+i-1] - sum[p] >= x) return 1;
    	}
    	return 0;
    }
    
    int main()
    {
    	n = read();
    	rep(i,1,n) a[i] = a[i+n] = read();
    	rep(i,1,n<<1) sum[i] = sum[i-1] + a[i];
    	ll L = 1,R = sum[n]/3;
    	while(L < R)
    	{
    		ll mid = (L+R+1) >> 1;
    		if(check(mid)) L = mid;
    		else R = mid - 1;
    	}
    	printf("%lld
    ",L);
    	return 0;
    }
    

    T3.断层
    这题是JOI 2016Final的T5.传送门

    自己是想不出来了。
    做法非常巧妙,因为斜着修改难以维护,所以我们整个将坐标轴旋转45度。(标程是顺时针但讲题时候是逆时针)
    这里说逆时针旋转。这样的话,k=1的操作相当于是给定一条竖着的直线,将其左边的点向上移,k=2的操作是给定一条横着的直线,将上面的点左移。
    显然可以想到用线段树/bit去维护横纵坐标。
    但是正着做是不行的,因为我们无法保证单调性。我们考虑倒推,倒着做所有的操作,改变操作方向。这时候我们发现,任意一次操作必然不会改变x,y之间的相对大小。(因为一开始每个点的坐标是(i,i),横纵坐标都递增。每次我们都是把更小的纵坐标下移,更大的横坐标右移)
    这样就能保证线段树/bit维护的每一个点的下标就是按照其原来的顺序排列的,直接这样倒着推回去,把坐标变换回来输出答案即可。
    变换的时候坐标从((x,y))((x+y,x-y)),所以回来的时候是((frac{x+y}{2},frac{x-y}{2}))
    具体的实现细节有很多,首先是旋转之后的线段长度,每个都是原来的(sqrt{2})倍,而原来每次上移1个单位相当于移动了(sqrt{2})个单位,所以要把移动长度乘以2。
    再者我们令每个点表示其右面的一块土地,所以坐标是从(0~n-1)的,而且对于涉及x的操作每个也要-1.
    线段树不知道为啥跑的死慢,用树状数组的时候要注意把x+1,否则容易卡死。
    每次需要用二分查找你修改的区间,复杂度(O(nlog^2n))

    #include<bits/stdc++.h>
    #define rep(i,a,n) for(int i = a;i <= n;i++)
    #define per(i,n,a) for(int i = n;i >= a;i--)
    #define enter putchar('
    ')
    #define lowbit(x) x & (-x)
    
    using namespace std;
    typedef long long ll;
    const int M = 400005;
    
    int read()
    {
       int ans = 0,op = 1;char ch = getchar();
       while(ch < '0' || ch > '9') {if(ch == '-') op = -1;ch = getchar();}
       while(ch >= '0' && ch <= '9') ans = ans * 10 + ch - '0',ch = getchar();
       return ans * op;
    }
    
    int n,q;
    
    struct quake
    {
       int x,l,d;
    }a[M];
    
    struct tarray
    {
       ll c[M];
       void add(int x,int val){x++;while(x < n+2) c[x] += val,x += lowbit(x);}
       ll ask(int x){x++;ll cur = 0;while(x) cur += c[x],x -= lowbit(x);return cur;}
       void modify(int l,int r,int val) {add(l,val),add(r+1,-val);}
    }tx,ty;
    
    int main()
    {
       n = read(),q = read();
       rep(i,1,q) 
       {
          a[i].x = read(),a[i].d = read(),a[i].l = read() << 1;
          if(a[i].d == 1) a[i].x--;
       }
       rep(i,0,n) tx.modify(i,i,i),ty.modify(i,i,i);
       per(i,q,1)
       {
          if(a[i].d == 1) 
          {
    	 int L = 0,R = n-1,ans = -1;
    	 while(L <= R)
    	 {
    	    int mid = (L+R) >> 1;
    	    ll k = tx.ask(mid);
    	    if(k <= a[i].x) ans = mid,L = mid + 1;
    	    else R = mid - 1;
    	 }
    	 if(ans != -1) ty.modify(0,ans,-a[i].l);
          }
          if(a[i].d == 2)
          {
    	 int L = 0,R = n-1,ans = -1;
    	 while(L <= R)
    	 {
    	    int mid = (L+R) >> 1;
    	    ll k = ty.ask(mid);
    	    if(k < a[i].x) L = mid + 1;
    	    else ans = mid,R = mid-1;
    	 }
    	 if(ans != -1) tx.modify(ans,n-1,a[i].l);
          }
       }
       rep(i,0,n-1) 
       {
          ll kx = tx.ask(i),ky = ty.ask(i);
          printf("%lld
    ",(kx-ky)>>1);
       }
       return 0;
    }
    
    
  • 相关阅读:
    SlickEdit 中 GDB 调试时SIG32 使得无法跟踪的问题 解决方法
    ln与mount
    ubuntu12.04 的 root 用户显示 中文 和 默认显示中文的方法
    ASP.NET MVC控制器作用
    ASP.NET管道模型
    第二章MVC框架如何截获请求
    第一章MVC与WebForms处理请求的区别
    asp.net运行原理一
    一个通配符引起的错误
    关于权限
  • 原文地址:https://www.cnblogs.com/captain1/p/10439396.html
Copyright © 2020-2023  润新知