2017icpc全國邀請賽(陝西)

賽後總結

首先想吐槽一下天花板會掉的酒店和自帶不明黃色痕跡的牀單
算了還是直接進入主題吧…..
熱身賽爆零了,一道猜題意一道是二分貪心,一道是數位dp+數論,cf上面的題,強肛二分貪心結果沒肛出來,真是蠢的不行.
正賽打的也很難看,先看到J題簽到直接輸出一個座標就OK,
然後是B題,題意是給我們一個序列,然後可以把序列中任意兩個數字進行交換,最多交換k次,求能夠得到的最大連續子段和.一開始往DP那方面去想,但是沒什麼思路,而且當時已經過穿了的題目,後來靈機一動,枚舉任意一個區間,然後把區間內前k小的數字和區間外前k大的數字進行交換.然後求一個最大值即可.
接下來是C題,隊友想的,方法大概就是一個簡單的貪心,沒什麼特別複雜的情況,直接貪心暴力就行,不過有個地方我覺得很可能會TLE,但是賽後出題人表示就是給一道簡單的貪心簽到,沒造這種數據.過完三個題一個半小時吧當時是48名,銀牌都沒壓力銅更是穩的不行,對於一個鐵牌選手來說我當時心裏已經非常激動,心態完全爆炸不太想寫題目,這也導致我們後面直接崩潰.
A題題意是有一個一行n列的01矩陣A,和一個n*m的01矩陣B,給定這兩個矩陣相乘後的矩陣(mod2),求A和B矩陣有多少種組合方案
三個小時沒什麼結果,還剩幾十分鐘的時候我仔細想一下想到枚舉A裏面的1的個數然後開始組合數亂搞,但是時間畢竟太緊了沒寫出來感覺好氣,賽後想到公式應該是(2^n - 1) * (2 ^ (n * m - m)) 如果給定的矩陣是全0,則還要加上一個2^(m*n)
K題題意是一個人要去參加一個婚禮,目的地在座標軸一個點上,當前在0點處,從一個點跳到下一個點需要一個單位時間,然後數軸上有一些點,可以向前跳yi步,但是要求必須連續走了zi步,問到達目的地的最少時間,(只能往前走不能往後走,總共10萬個點)
出題人說這個題怎麼最短路和dp都行,最短路建邊應該不是很複雜,堆優化一些dijkstra應該就可以了,具體沒想,想了一個dp方程
雖然數軸的數字比較大,有1e9,但是實際上我們只關心那些能跳的點,它要從哪裏開始連續走,然後可以跳到哪裏,因此實際上只有最多30萬個點.
對於每一個點,它可以由前面的點走過來即,dp[i] = min(dp[j] + x[i] - x[j] )(0<= j < i)
同時i點可能由前面某些點跳到,枚舉那些能跳到他的點j dp[i] = min(dp[i] , dp[j - zj] + zj) (這個地方要用map哈希一下),
雖然還沒交(目前爲止沒有地方可以交),但是感覺應該差不多了,把代碼貼一下 等什麼時候能交的時候交一下看看.

#include<cmath>
#include<algorithm>
#include<cstring>
#include<string>
#include<set>
#include<map>
#include<time.h>
#include<cstdio>
#include<vector>
#include<list>
#include<stack>
#include<queue>
#include<iostream>
#include<stdlib.h>
using namespace std;
#define  LONG long long
const int   INF=0x3f3f3f3f;
const LONG  MOD=1e9+ 7;
const double PI=acos(-1.0);
#define clrI(x) memset(x,-1,sizeof(x))
#define clr0(x) memset(x,0,sizeof x)
#define clr1(x) memset(x,INF,sizeof x)
#define clr2(x) memset(x,-INF,sizeof x)
#define EPS 1e-10
#define lson  l , mid , rt<< 1
#define rson  mid + 1 ,r , (rt<<1)+1
#define root 1, m , 1
struct Node
{
    int x , y ,z ;
}node[100100] ;
int point[400400] ;
int tmp[400400] ;
int L ;
int dp[400400] ;
int F[400400] ;
int main()
{
    int T ;
    cin >> T ;
    while(T --)
    {
        int n ;
        scanf("%d%d",&n , &L) ;
        for(int i = 1; i <= n ; ++i)
        scanf("%d%d%d",&node[i].x, &node[i].y , &node[i].z) ;
        map<int , int >mp1 ;
        map<int , int >mp;
        map<int , int > jump ;
        map<int , int >mp2 ;
        jump.clear() ;
        mp1.clear() ;
        mp.clear() ;
        mp2.clear() ;
        int tot = 0 ;
        for(int i = 1 ; i<= n ;++i)
        {
            int _x1 ,_x2 ,_x3;
            int j1 =0 , j2 = 0 , j3 = 0 ;
            //
            _x1 = node[i].x ;
            if(_x1 >= 0 && _x1 <= L)
            tmp[++tot] = _x1 ,j1 = 1;
             //
            _x2 = node[i].x - node[i].z ;
            if(_x2 >= 0 && _x2 <= L)
            {
                tmp[++tot] = _x2 ;
                j2 = 1 ;
            }
            //
            _x3 = node[i].x + node[i].y ;
            if(_x3 >= 0 && _x3 <= L)
            {
                tmp[++tot] = _x3 ;
                j3 = 1;
            }
            if( j1 && j2 && j3)
             mp1[node[i].x] =  _x3 ,
                mp2[node[i].x] = _x2 ,
                jump[node[i].x] = 1;
        }
        sort(tmp + 1, tmp + tot + 1) ;
        int p = 1;
        point[p] = tmp[1] ;
        for(int i = 2;i <= tot ; ++i)
        if(tmp[i] != point[p])
            point[++p] = tmp[i] ;
        for(int i = 1; i<= p ;++i)
        mp[point[i]] = i;
        //
        for(int i =1; i<= p ; ++ i)
        printf("%d ",point[i]) ;cout<<endl;
        //
        clr1(dp) ;
        dp[1] = point[1] ;
        int res = dp[1] -point[1] ;
        if(jump[point[1]])
        {
            int t = mp[ mp1[point[1] ]] ;
            int t2 = mp[mp2[point[1]]] ;
            dp[t] = min(dp[t] , dp[t2] + point[1] - mp2[point[1]]) ;
        }
        for(int i = 1; i <= p ; ++i )
        {
            dp[i] = min(dp[i] , point[i] + res ) ;
            dp[i] = min(dp[i] , point[i] ) ;
            if(jump[point[i]])
            {
                int t = mp[ mp1[point[i] ]] ;
                int t2 = mp[mp2[point[i]]] ;
                dp[t] = min(dp[t] , dp[t2] + point[i] - mp2[point[i]]) ;
            }
            res = min(res , dp[i] - point[i] ) ;

        }
        for(int i =1; i<= p ; ++i)
        printf("%d ",dp[i]);cout<<endl;
        int ans = INF ;
        for(int i = 1;i <= p ; ++ i)
            ans = min(ans , L - point[i] + dp[i]);
        cout<<ans<<endl;

    }
}

感覺題目還是做的太少了啊 ,還是太弱了,很多題其實都是可以寫出來的,但是現場有時候是沒勇氣,有時候方向沒想對,總的來說還是太vegetable了

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章