2018.7.24日記&總結

今天是我們組出題,也做了一下。過了4題,感覺題目難度不大。多想想歐拉路那道題說不定也可以做。還順帶過了不是今天比賽的一道線段樹合併。感覺代碼能力的確有所提高(算是恢復)。但是離應有的狀態還是差很遠!
今天的幾何題很簡單但是沒有去寫,因爲幾何的板子太陌生。其實幾何的東西不多,只要熟悉幾個基本的模型,就比較好做。一定不要期望ACM隊裏有人幫你寫幾何題,因此這個假期一定要練好幾何!每天至少1道。先把板子敲熟再應用。做到輕鬆過題。
今天下午和晚上的狀態很差,寫題效率極低,必須反思!堅持到最後一刻!不能放鬆!適當的運動後應該靜下心來寫題!控制住自己!高效的寫題!
今天我出的題(雖然不是原創)感覺還是不錯的。然而沒有人來寫,有點小遺憾!
這兩天的題還有4道沒有調你在幹什麼,明天必須一起全部調完!!!

題解:
A:推結論。然後暴力。挺顯然的,就是思維要放開

B:幾何。圓與矩形求交轉化成把矩形擴展(四角變成1/4圓)和圓心運動的直線求交。
今天沒有寫完(打球去了,忘了自己應該做的事!)明天寫

C:簽到題。WA了兩發因爲沒有看清楚題意。題目上說的是prime number

D:每個位置有pi概率爲1,求區間連續1的長度3次方的期望。單點修改。
把dp貢獻差分,維護1,2,3次,矩陣快速冪維護轉移。利用矩陣的結合律(直接DP無法結合)
經典題

//把f數組維護成貢獻增加(前綴和),矩陣快速冪的時候就不用記ans了,優化一維
//線段樹維護矩陣,動態DP,經典思想。因爲矩陣滿足結合律,而直接dp無法統計左邊對右邊的貢獻
#pragma GCC optimize(3)
#include<bits/stdc++.h>
using namespace std;
#define maxn 200020
#define rep(i,l,r) for(register int i = l ; i <= r ; i++)
#define repd(i,r,l) for(register int i = r ; i >= l ; i--)
#define inf 1e8


typedef long long ll;
inline int read(){
    register int num = 0;
    register char ch = getchar();
    while ( ch > '9' || ch < '0' ) ch = getchar();
    while ( ch <= '9' && ch >= '0' ) num = num * 10 + ch - '0' , ch = getchar();
    return num;
}
int num[10];
inline void write(int x){
    register int cnt = 0;
    if ( !x ){ printf("0"); return; } //一定要特判0!!!
    while ( x ) num[++cnt] = x % 10 , x /= 10;
    while ( cnt ) putchar(num[cnt--] + '0');
}
double a[4][4],b[4][4],tmp[4][4],p[maxn],mtx[maxn][4][4];
int ls[maxn],rs[maxn],tot,root;
int n,m,T;

void clear(){
    rep(i,0,tot) memset(mtx[i],0,sizeof(mtx[i])) , ls[i] = rs[i] = 0;
    tot = root = 0;
}
inline void power(double a[4][4],double b[4][4],double c[4][4]){
    memset(tmp,0,sizeof(tmp));
//rep(i,0,4) rep(j,0,4) tmp[i][j] = 0;
    rep(i,0,3) rep(j,0,3) rep(k,0,3) tmp[i][j] += b[i][k] * c[k][j];
    memcpy(a,tmp,sizeof(tmp));
}
void update(int x){
    power(mtx[x],mtx[ls[x]],mtx[rs[x]]);
}
void build(int &x,int l,int r){
    x = ++tot;
    if ( l == r ){
        mtx[x][1][1] = mtx[x][2][2] = mtx[x][0][3] = mtx[x][1][3] = mtx[x][2][3] = p[l];
        mtx[x][0][1] = mtx[x][0][2] = p[l] * 3 , mtx[x][1][2] = p[l] * 2;
        mtx[x][0][0] = mtx[x][3][3] = 1;
        return;
    }
    int mid = (l + r) >> 1;
    build(ls[x],l,mid) , build(rs[x],mid + 1,r);
    update(x);
}
void modify(int x,int l,int r,int id,double cp){
    if ( l == r ){
        p[l] = cp;
        mtx[x][1][1] = mtx[x][2][2] = mtx[x][0][3] = mtx[x][1][3] = mtx[x][2][3] = p[l];
        mtx[x][0][1] = mtx[x][0][2] = p[l] * 3 , mtx[x][1][2] = p[l] * 2;
        mtx[x][0][0] = mtx[x][3][3] = 1;
        return;
    }
    int mid = (l + r) >> 1;
    if ( id <= mid ) modify(ls[x],l,mid,id,cp);
    else modify(rs[x],mid + 1,r,id,cp);
    update(x);
}
void query(int x,int l,int r,int L,int R,double a[4][4]){
    if ( L <= l && R >= r ) { power(a,a,mtx[x]); return; }
    int mid = (l + r) >> 1;
    if ( L <= mid ) query(ls[x],l,mid,L,R,a);
    if ( R > mid ) query(rs[x],mid + 1,r,L,R,a);
}
int main(){
//  freopen("input.txt","r",stdin);
    scanf("%d",&T);
    while ( T-- ){
        clear();
        scanf("%d",&n);
        rep(i,1,n) scanf("%lf",&p[i]);
        build(root,1,n);
        scanf("%d",&m);
        while ( m-- ){
            int tp,x,l,r; double cp;
            scanf("%d",&tp);
            if ( tp == 1 ){
                scanf("%d %lf",&x,&cp); 
                modify(root,1,n,x,cp);
            }
            else{
                scanf("%d %d",&l,&r);
                memset(a,0,sizeof(a));
                rep(i,0,3) a[i][i] = 1;
                query(root,1,n,l,r,a); 
                double ans = a[0][3];
                printf("%.2f\n",ans);
            }
        }
    }
    return 0;
}

E:一道歐拉回路的好題。[1,m]的數各出現n次,每次與0交換(開始0在末尾)使[k * m + 1,k *m + m]的區間中[1,m]恰好各出現一次。
對於每一個區間,如果一個值多了則向該數連邊,少了則該數向它連邊。對於每個聯通塊找歐拉回路。因爲出入度相等所以一定存在。
輸出方案在歐拉回路退棧的時候推下細節。非常好寫。但是因爲看錯數據範圍調了很久!很不應該!
求歐拉回路要邊要dfs完後加入棧,保證邊的順序

//看清數據範圍再寫題!!!
#include<bits/stdc++.h>
using namespace std;
#define maxn 820
#define N 200020
#define rep(i,l,r) for(register int i = l ; i <= r ; i++)
#define repd(i,r,l) for(register int i = r ; i >= l ; i--)
#define inf 1e8

struct node{
    int next,to,from;
}e[N];
struct node2{
    int x,y;
};
int head[maxn],cnt;
int n,m,T,stack_[N],tops,tag[N];
int a[maxn][maxn],num[maxn][maxn],tmp,vis[maxn];
vector <int> vec[maxn][maxn];
vector <node2> ans;

void clear(){
    rep(i,1,n + m) vis[i] = head[i] = 0;
    rep(i,1,n) rep(j,1,m) num[i][j] = 0 , vec[i][j].clear();
    rep(i,1,cnt) tag[i] = 0;
    ans.clear(); cnt = 0;
}
inline void adde(int x,int y){
    e[++cnt].to = y;
    e[cnt].next = head[x];
    e[cnt].from = x;
    head[x] = cnt;
}
void dfs(int x){
    vis[x] = 1;
    for (int i = head[x] ; i ; i = e[i].next){
        if ( tag[i] ) continue;
        tag[i] = 1;
        dfs(e[i].to);
        stack_[++tops] = i; //求歐拉回路要後加入棧,保證邊的順序
    }
}
int main(){
    freopen("input.txt","r",stdin);
    freopen("1.out","w",stdout);
    while ( ~scanf("%d %d",&n,&m) ){
        tmp = n * m + 1;
        rep(i,1,n){
            rep(j,1,m) scanf("%d",&a[i][j]) , vec[i][a[i][j]].push_back((i - 1) * m + j) , num[i][a[i][j]]++;
            rep(j,1,m){
                if ( !num[i][j] ) adde(j,m + i);
                else rep(k,2,num[i][j]) adde(m + i,j);
            }
        }
        rep(i,m + 1,n + m){
            if ( !vis[i] ){
                int fir = head[i],id,cur,last,num;
                tops = 0 , dfs(i);
                if ( !fir ) continue;
                last = vec[i - m][e[fir].to].back();
                vec[i - m][e[fir].to].pop_back();
                ans.push_back((node2){last,tmp});
                for(int j = 1 ; j <= tops ;j++){
                    id = stack_[j], num = e[id].from;
                    id = stack_[++j];
                    if ( j == tops ) cur = n * m + 1;   
                    else{
                        cur = vec[e[id].from - m][num].back();
                        vec[e[id].from - m][num].pop_back();    
                    }
                    ans.push_back((node2){last,cur});
                    last = cur;
                }
            }
        }
        printf("%d\n",ans.size());
        for (int i = 0 ; i < ans.size() ; i++){
            printf("%d %d\n",ans[i].x,ans[i].y);
        }
        clear();
    }
    return 0;
}

F:求最少刪多少個數是最長上升子序列變短。
按f[i](dp值)分層建圖。最小割。
好久沒寫網絡流的題。考場上現場yy出來的。
但是應該加強網絡流的練習,別把強項丟了

G:我自己的題。見我的出題日誌。

最後,提醒幾點:
1。早點睡,保證考試時精力充沛!
2。一定要複習,有10多天沒有複習以前的題了
3。堅持到最後一刻,一直到開學都不能有一點鬆懈。把自己的弱項靜心補起來,相信自己OI的實力!
4。明天打好翻盤仗!靜下心來思考!爭取過5題!進入前5名!

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