Codeforces Round #179 (Div. 2)A、B、C、D

來源:互聯網
上載者:User

題目連結

A.Yaroslav and Permutations

題意:

   n個元素的數組,每個元素不超過1000,可以交換相鄰兩個元素,問是否可以在有限次的操作之後使得相鄰兩個元素的值不相同。

#include <stdio.h>#include <string.h>int cnt[1005];int main(){    int n, a;    while (scanf("%d", &n) != EOF)    {        memset(cnt, 0, sizeof(cnt));        for (int i = 0; i < n; i++)        {            scanf("%d",&a);            cnt[a]++;        }        int m = -1;        for (int i = 0; i <= 1000;i++)        {            if (cnt[i] > m)                m = cnt[i];        }        if (n%2 == 0)        {            if (m > (n/2))                puts("NO");            else                puts("YES");        }        else        {            if (m > (n/2+1))                puts("NO");            else                puts("YES");        }    }    return 0;}

B.Yaroslav and Two Strings(轉載 原文地址)

對於兩個字串ch1和ch2,開四個數組a[i],b[i],c[i],d[i]分別表示 所有的情況數 、ch1[i]<=ch2[i]的情況數、ch1[i]>=ch2[i]的情況數、ch1[i]==ch2[i]的情況數,那麼根據容斥原理,有ans = ∏a[i] - ∏b[i] - ∏c[i] + ∏d[i]。

代碼

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#include <vector>#include <set>#include <map>#include <cmath>#include <queue>using namespace std;template <class T> void checkmin(T &t,T x) {if(x < t) t = x;}template <class T> void checkmax(T &t,T x) {if(x > t) t = x;}template <class T> void _checkmin(T &t,T x) {if(t==-1) t = x; if(x < t) t = x;}template <class T> void _checkmax(T &t,T x) {if(t==-1) t = x; if(x > t) t = x;}typedef pair <int,int> PII;typedef pair <double,double> PDD;typedef long long ll;#define foreach(it,v) for(__typeof((v).begin()) it = (v).begin(); it != (v).end ; it ++)#define MOD 1000000007int n ;ll a[101000] , b[101000] , c[101000] , d[101000];char ch1[101000] , ch2[101000];void gcd(ll a , ll b , ll &d , ll &x , ll &y) {    if(!b) {d = a; x = 1; y = 0;}    else { gcd(b , a%b,d,y , x); y -= x * (a/b); }}ll inv(ll a , ll n) {    ll d , x , y;    gcd(a , n , d,  x , y);    return d == 1 ? (x+n)%n : -1;}void debug() {    for(int i=0;i<n;i++) cout << a[i] << " ";    cout << endl;    for(int i=0;i<n;i++) cout << b[i] << " ";    cout << endl;    for(int i=0;i<n;i++) cout << c[i] << " ";    cout << endl;    for(int i=0;i<n;i++) cout << d[i] << " ";    cout << endl;}int main() {    cin >> n;    scanf("%s%s",ch1,ch2);    for(int i=0;i<n;i++) {        if(ch1[i] == '?' && ch2[i] == '?') { a[i] = b[i] = 55;c[i] = 10; d[i] = 100; }        else if(ch1[i] == '?') { a[i] = ch2[i] - '0'+1; b[i] = 11-a[i]; c[i] = 1; d[i] = 10; }        else if(ch2[i] == '?') { b[i] = ch1[i] - '0'+1; a[i] = 11-b[i]; c[i] = 1; d[i] = 10; }        else {            if(ch1[i] <= ch2[i]) a[i] = 1;            if(ch1[i] >= ch2[i]) b[i] = 1;            if(ch1[i] == ch2[i]) c[i] = 1;            d[i] = 1;        }    }    ll a1 = 1 , a2 = 1 , a3 = 1 , a4 = 1;        for(int i=0;i<n;i++) {            a1 *= a[i]; a1 %= MOD;            a2 *= b[i]; a2 %= MOD;            a3 *= c[i]; a3 %= MOD;            a4 *= d[i]; a4 %= MOD;        }        ll ans = (a4-a1-a2+a3) % MOD;        if(ans < 0) ans += MOD;        cout << ans << endl;        //debug();    return 0;}


C.Greg and Array

題意:

       一個數組n個數,然後又m組操作,每組操作是將從l到r 的每個元素值加v,然後是k組操作,每組的意思是執行第x、x+1……y組操作,然後輸出數組元素。

思路:

      對於區間修改的問題,毫無疑問是用線段樹,但這裡有兩個線段樹,不過我們在這裡只對數組建樹,不對操作次數建樹,用lazy的思想,我們可以更簡單的知道那組操作執行了多少次,然後再更新線段樹,正好更新的val值是該操作的原來的v乘以操作次數。

代碼:

#include <stdio.h>#include <string.h>typedef __int64 ll;const ll maxn = 100005;ll a[maxn];struct node{    ll l, r, m;    ll sum, mark;}tree[maxn<<2];ll cnt[maxn];struct operation{    ll l, r, v;}op[maxn];void build(ll l, ll r, ll o){    tree[o].l = l;    tree[o].r = r;    ll m = (l+r)>>1;    tree[o].m = m;    tree[o].mark = 0;    if (l == r)    {        tree[o].sum = a[l];        return;    }    build(l, m, o<<1);    build(m+1, r, (o<<1)+1);    tree[o].sum = tree[o<<1].sum + tree[(o<<1)+1].sum; } void update(ll l, ll r, ll v, ll o) {     if (tree[o].l == l && tree[o].r == r)     {        tree[o].mark += v;        return;     }     tree[o].sum += (ll)(r-l+1)*v;     if (tree[o].m >= r)        update(l, r, v, o<<1);     else if (l > tree[o].m)        update(l, r, v, (o<<1)+1);     else     {         update(l, tree[o].m, v, o<<1);         update(tree[o].m+1, r, v, (o<<1)+1);     } }ll query(ll l, ll r, ll o) {     if (tree[o].l == l && tree[o].r == r)        return tree[o].sum + tree[o].mark*(r-l+1);     if (tree[o].mark != 0)     {         tree[o<<1].mark += tree[o].mark;         tree[(o<<1)+1].mark += tree[o].mark;         tree[o].sum += (ll)(tree[o].r -tree[o].l +1)*tree[o].mark;         tree[o].mark = 0;     }     if (tree[o].m >= r)        return query(l, r, o<<1);     else if (tree[o].m <l)        return query(l, r, (o<<1)+1);     else        return query(l, tree[o].m, o<<1) + query(tree[o].m+1, r, (o<<1)+1); }int main(){    ll n, m, k, l, r, x;    while (scanf("%I64d%I64d%I64d",&n,&m,&k) != EOF)    {        for(ll i = 1; i <= n; i++)            scanf("%I64d",&a[i]);        build(1, n, 1);        for (ll i = 1; i <= m; i++)            scanf("%I64d %I64d %I64d",&op[i].l, &op[i].r, &op[i].v);        memset(cnt, 0, sizeof(cnt));        for (ll i = 1; i <= k; i++)        {            scanf("%I64d %I64d",&l, &r);            cnt[l] += 1;            cnt[r+1] -= 1;        }        ll sum = 0;        for (ll i = 1; i <= m; i++)        {            sum += cnt[i];                              //lazy的思想            update(op[i].l, op[i].r, sum*op[i].v, 1);        }        for (ll i = 1; i < n; i++)            printf("%I64d ",query(i, i, 1));        printf("%I64d\n",query(n, n, 1));    }    return 0;}

D.Greg and Graph (轉載  原文)

在講這道題之前我先現簡要介紹一下Floyd—Warshall演算法,方便大家更好的瞭解這道題。

Floyd—Warshall演算法的原理是動態規劃。

設D[i][j][k]為從i到j只以1~k中節點為中間結點的最短路徑長度,則:

(1)若最短路徑經過點k,那麼D[i][j][k]=D[i][k][k-1]+D[k][j][k-1]

(2)若最短路徑不經過點k,那麼D[i][j][k]=D[i][j][k-1]

因此D[i][j][k]=min(D[i][k][k-1]+D[k][j][k-1],D[i][j][k]=D[i][j][k-1]).

如果我們把k放在最外層的迴圈,那麼第三位在實現上可以省去。

這道題可以反著思考,我們考慮從一個點開始一個個添加,那麼答案倒著輸出就行了。

我們每次加進來的點相當於k,首先需要進行一個雙重迴圈找到k點和所有點之間的最短路徑;然後就以k點位判斷節點更新之前的k-1個點,時間複雜度降到O(n^3),而暴力解法每次都要進行floyd,時間複雜度為O(n^4);相比之下前述解法考慮到了floyd演算法的性質,更好了運用了演算法的內質。

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#include <vector>#include <set>#include <map>#include <cmath>#include <queue>using namespace std;template <class T> void checkmin(T &t,T x) {if(x < t) t = x;}template <class T> void checkmax(T &t,T x) {if(x > t) t = x;}template <class T> void _checkmin(T &t,T x) {if(t==-1) t = x; if(x < t) t = x;}template <class T> void _checkmax(T &t,T x) {if(t==-1) t = x; if(x > t) t = x;}typedef pair <int,int> PII;typedef pair <double,double> PDD;typedef long long ll;#define foreach(it,v) for(__typeof((v).begin()) it = (v).begin(); it != (v).end ; it ++)int n ;const int N = 555;int g[N][N];ll ans[N];int a[N];int main() {    cin >> n;    for(int i=1;i<=n;i++)    for(int j=1;j<=n;j++) cin >> g[i][j];    for(int i=n;i>=1;i--) cin >> a[i];    ans[1] = 0;    for(int i=2;i<=n;i++) {        int aa = a[i];        ans[i] += ans[i-1];        for(int j=1;j<i;j++)            ans[i] += g[a[i]][a[j]] + g[a[j]][a[i]];        for(int j=1;j<i;j++)        for(int k=1;k<i;k++) {            if(g[a[j]][a[i]] > g[a[j]][a[k]]+g[a[k]][a[i]]) {                ans[i] -= g[a[j]][a[i]];                ans[i] += g[a[j]][a[k]]+g[a[k]][a[i]];                g[a[j]][a[i]] = g[a[j]][a[k]]+g[a[k]][a[i]];            }            if(g[a[i]][a[j]] > g[a[i]][a[k]] + g[a[k]][a[j]]) {                ans[i] -= g[a[i]][a[j]];                ans[i] += g[a[i]][a[k]] + g[a[k]][a[j]];                g[a[i]][a[j]] = g[a[i]][a[k]] + g[a[k]][a[j]];            }        }        for(int j=1;j<i;j++)        for(int k=1;k<i;k++) {            if(g[a[j]][a[k]] > g[a[j]][a[i]] + g[a[i]][a[k]]) {                ans[i] -= g[a[j]][a[k]];                ans[i] += g[a[j]][a[i]] + g[a[i]][a[k]];                g[a[j]][a[k]] = g[a[j]][a[i]] + g[a[i]][a[k]];            }        }    }    cout << ans[n];    for(int i=n-1;i>=1;i--) cout << " "<< ans[i];    cout << endl;    return 0;}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.