顯示具有 USACO 2014 標籤的文章。 顯示所有文章
顯示具有 USACO 2014 標籤的文章。 顯示所有文章

2016年11月29日 星期二

USACO 2014 US Open, Silver Problem 2. Dueling GPSs

http://www.usaco.org/index.php?page=viewproblem2&cpid=434

第一次用dijkstrea

(待補詳解)


//first time to ude dijistra
#include <iostream>
#include <stdio.h>
#include <cstring>
#include <utility>
#include <queue>
#include <algorithm>
#include <vector>
#include <cassert>
using namespace std;

#define MP make_pair
#define F first
#define S second
typedef pair<int,int> pii;
typedef pair<int,pii> piii;
const int MAX_N = 1e4 + 6;
const int MAX_M = 1e5 + 6;
const int INF = 1e9 + 7;

vector<pii> edg[MAX_N];
int a[MAX_M],b[MAX_M],p[MAX_M],q[MAX_M],r[MAX_M];
int d[MAX_N];

#define int long long

main () {
    if (fopen("gpsduel.in","r")) {
        freopen("gpsduel.in","r",stdin);
        freopen("gpsduel.out","w",stdout);
    }
//    freopen("5.in","r",stdin);
    int n,m;
    while (scanf("%lld %lld",&n,&m) != EOF) {
        for (int x=0;n>=x;x++) {
            edg[x].clear();
        }
        for (int x=1;m>=x;x++) {
            scanf("%lld %lld %lld %lld",&a[x],&b[x],&p[x],&q[x]);
            a[m+x]=b[x];
            b[m+x]=a[x];
            p[m+x]=p[x];
            q[m+x]=q[x];
            edg[a[x]].push_back(make_pair(b[x],x));
            edg[b[x]].push_back(make_pair(a[x],m+x));
            r[x] = 2;
            r[m+x] = 2;
        }
        //decide route P
        priority_queue<piii,vector<piii>,greater<piii> > pq;
        fill(d,d+MAX_N,INF);
        d[n]=0;
        pq.push(MP(0,MP(n,2*m+1)));  //value,to,from(the id)
        while (!pq.empty()) {
            piii tmp=pq.top();
            pq.pop();
            int t=tmp.S.F;
            if (d[t] < tmp.first) continue;
            else if (d[t] == tmp.first) {
                if (tmp.second.S!=2*m+1) r[(tmp.second.S>m?tmp.second.S-m:tmp.S.S+m)]--;
                if (tmp.second.S!=2*m+1) continue;
            }
            else if (d[t] > tmp.first) {
                if (tmp.second.S!=2*m+1) r[(tmp.second.S>m?tmp.second.S-m:tmp.S.S+m)]--;
                d[t]=tmp.first;
            }
            for (auto i=edg[t].begin();i!=edg[t].end();i++) {
                pii tmp=*i;
                int x=tmp.first,y=tmp.second;
                if (y<=m) continue;
                if (d[x] >= d[t] + p[y]) {
                    pq.push(MP(d[t] + p[y],MP(x,y)));
                }
            }
        }
//        for (int x=1;2*m>=x;x++) cout<<"r["<<x<<"] = "<<r[x]<<endl;
        //decide route Q
        fill(d,d+MAX_N,INF);
        d[n]=0;
        pq.push(MP(0,MP(n,2*m+1)));  //value,to,from(the id)
        while (!pq.empty()) {
            piii tmp=pq.top();
            pq.pop();
            int t=tmp.S.F;
            if (d[t] < tmp.first) continue;
            else if (d[t] == tmp.first) {
                if (tmp.second.S!=2*m+1) r[(tmp.second.S>m?tmp.second.S-m:tmp.S.S+m)]--;
                if (tmp.second.S!=2*m+1) continue;
            }
            else if (d[t] > tmp.first) {
                if (tmp.second.S!=2*m+1) r[(tmp.second.S>m?tmp.second.S-m:tmp.S.S+m)]--;
                d[t]=tmp.first;
            }
            for (auto i=edg[t].begin();i!=edg[t].end();i++) {
                pii tmp=*i;
                int x=tmp.first,y=tmp.second;
                if (y<=m) continue;
                if (d[x] >= d[t] + q[y]) {
                    pq.push(MP(d[t] + q[y],MP(x,y)));
                }
            }
        }
//        for (int x=1;2*m>=x;x++) {
//            if (r[x] < 0)cout<<"r["<<x<<"] = "<<r[x]<<endl;
//            assert(0<=r[x]);
//        }
        //count the answer now
        fill(d,d+MAX_N,INF);
        d[1]=0;
        pq.push(MP(0,MP(1,2*m+1)));  //value,to,from(the id)
        while (!pq.empty()) {
            assert(pq.size() <= m);
            piii tmp=pq.top();
            pq.pop();
            int t=tmp.S.F;
//            cout<<"t = "<<t<<endl;
            if (d[t] <= tmp.first && t!=1) continue;
            if (d[t] > tmp.first) {
                d[t] = tmp.first;
            }
            for (auto i=edg[t].begin();i!=edg[t].end();i++) {
                pii tmp=*i;
                int x=tmp.first,y=tmp.second;
                if (y>m) continue;
                if (d[x] > d[t] + r[y]) {
                    pq.push(MP(d[t] + r[y],MP(x,y)));
                }
            }
        }
        printf("%lld\n",d[n]);
    }
}


2016年3月10日 星期四

USACO 2014 December Contest, Gold Problem 2. Marathon

http://www.usaco.org/index.php?page=viewproblem2&cpid=495

一開始也不知道這題是在做什麼
之後想想我們似乎要維護個兩點之間距離 + 跨一點的距離
然後似乎很麻煩
題解也不知道要怎麼寫XD
往上面兩個方向仔細去想即可

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <vector>
#include <utility>
#include <cmath>
using namespace std;
typedef long long LL;

const int MAX_N = 100003;

LL pre_seg[400021];
LL two_seg[400021];

LL d[MAX_N];
LL d2[MAX_N];

void Build(int id,int L,int R) {
if (L==R) {
pre_seg[id] = d[L];
return;
}
int mid=(L+R)>>1;
Build(id*2,L,mid);
Build(id*2+1,mid+1,R);
pre_seg[id]=pre_seg[id*2]+pre_seg[id*2+1];
}

void modify(int id,int L,int R,int pos,int val) {
if (L==R) {
pre_seg[id]=val;
return;
}
int mid=(L+R)>>1;
if (pos<=mid) modify(id*2,L,mid,pos,val);
else modify(id*2+1,mid+1,R,pos,val);
pre_seg[id]=pre_seg[id*2]+pre_seg[id*2+1];
}

int query(int id,int L,int R,int l,int r) {
if (L>r || l > R) return 0;
if (l<=L && R<=r) {
return pre_seg[id];
}
int mid=(L+R)>>1;
return query(id*2,L,mid,l,r)+query(id*2+1,mid+1,R,l,r);
}

void Build2(int id,int L,int R) {
if (L==R) {
two_seg[id]=d2[L];
return;
}
int mid=(L+R)>>1;
Build2(id*2,L,mid);
Build2(id*2+1,mid+1,R);
two_seg[id]=max(two_seg[id*2],two_seg[id*2+1]);
}

void modify2(int id,int L,int R,int pos,int val) {
if (L==R) {
two_seg[id]=val;
return;
}
int mid=(L+R)>>1;
if (pos<=mid) modify2(id*2,L,mid,pos,val);
else modify2(id*2+1,mid+1,R,pos,val);
two_seg[id]=max(two_seg[id*2],two_seg[id*2+1]);
}

int query2(int id,int L,int R, int l,int r) {
if (l>r) return 0;
if (L>r || l > R) return 0;
else if (l<=L && R<=r) return two_seg[id];
int mid=(L+R)>>1;
return max(query2(id*2,L,mid,l,r),query2(id*2+1,mid+1,R,l,r));
}

int x[MAX_N];
int y[MAX_N];

int main () {
freopen("marathon.in","r",stdin);
freopen("marathon.out","w",stdout);
int n,q;
while (scanf("%d %d",&n,&q) != EOF) {
for (int i=1;n>=i;i++) {
scanf("%d %d",&x[i],&y[i]);
if (i>1) {
d[i-1]=abs(x[i]-x[i-1]) + abs(y[i]-y[i-1]);
}
if (i>2) {
d2[i-2]=d[i-2]+d[i-1]-abs(x[i]-x[i-2])-abs(y[i]-y[i-2]);
}
}
Build(1,1,n-1);
Build2(1,1,n-2);
for (int i=0;q>i;i++) {
char t;
cin >> t;
if (t=='Q') {
int i,j;
scanf("%d %d",&i,&j);
printf("%d\n",query(1,1,n-1,i,j-1)-query2(1,1,n-2,i,j-2));
}
else {
int i,j,k;
scanf("%d %d %d",&i,&j,&k);
x[i]=j;
y[i]=k;
if (i>1&&n>i) {
d[i-1]=abs(x[i]-x[i-1]) + abs(y[i]-y[i-1]);
modify(1,1,n-1,i,abs(x[i+1]-x[i])+abs(y[i+1]-y[i]));
d[i]=abs(x[i+1]-x[i]) + abs(y[i+1]-y[i]);
modify(1,1,n-1,i-1,abs(x[i]-x[i-1])+abs(y[i]-y[i-1]));
}
else if (i==1) {
d[i]=abs(x[i+1]-x[i]) + abs(y[i+1]-y[i]);
modify(1,1,n-1,i,abs(x[i+1]-x[i])+abs(y[i+1]-y[i]));
}
else if (i==n) {
d[i-1]=abs(x[i]-x[i-1]) + abs(y[i]-y[i-1]);
modify(1,1,n-1,i-1,abs(x[i]-x[i-1])+abs(y[i]-y[i-1]));
}
if (i>2) d2[i-2]=d[i-2]+d[i-1]-abs(x[i]-x[i-2])-abs(y[i]-y[i-2]);
if (i>1&&i<n) d2[i-1]=d[i-1]+d[i]-abs(x[i+1]-x[i-1])-abs(y[i+1]-y[i-1]);
if (i<n-1)d2[i]=d[i]+d[i+1]-abs(x[i+2]-x[i])-abs(y[i+2]-y[i]);
if (i>2) modify2(1,1,n-2,i-2,d2[i-2]);
if (i>1 && i<n) modify2(1,1,n-2,i-1,d2[i-1]);
if (i<n-1) modify2(1,1,n-2,i,d2[i]);
}
}
// cout<<"---\n";
// for (int x=1;n-1>=x;x++) printf("%d\n",query(1,1,n-1,x,x));
// cout<<"---\n";
// for (int x=1;n-2>=x;x++) printf("%d\n",query2(1,1,n-2,x,x));
// for (int x=1;n-2>=x;x++) cout<<"d2["<<x<<"]="<<d2[x]<<endl;
}
}