2019 Nanjing network game

A The beautiful values of the palace

Knowledge Point: Analog, Fenwick tree + prefix and two-dimensional discrete +

  1. The calculated coordinate value (as a first center, and then subtracting n * n, in turn easier to count)
  2. The special points to queue
  3. Reads the inquiry, the inquiry \ ((x_1, Y_1, x_2, y_2) \) , if \ (mp [x] [y ] \) as a prefix and a two-dimensional, the answer is \ (mp [x_2] [y_2 ] -mp [x_2] [y_1-1] -mp [x_1-1] [y_2] + mp [x_1-1] [y_1-1] \)
  4. All query prefix requires a two-dimensional coordinates obtained also queued to be sorted according to a first reference x, y of discretization
  5. After ordering from small to large order of consideration, that is, x is from small to large consideration, every time they meet a new special point on the array is inserted into the tree, interrogated \ ((x, y) \ ) in Fenwick tree query (1, y-1) and can.
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1000010;
int T;
int n,m,p;
ll d[N],c[N];
struct node{
    int x1,y1,x2,y2;
};
vector<node> qu;//查询
struct Node{
    int x,y;
    int type;//type为0表示添加新点
}a[N];
bool cmp(Node a,Node b){
    if(a.x == b.x){
        if(a.y == b.y)return a.type == 0;
        return a.y < b.y;
    }
    return a.x < b.x;
}
vector<int> v;//离散y
void add(int x,int y){
    for(;x<N;x+=x&-x)c[x] += y;
}
ll ask(int x){
    ll res = 0;
    for(;x;x-=x&-x)res += c[x];
    return res;
}
map<int,map<int,int>> mp;
int id[N];
ll get(int x,int y){
    int cx = n / 2 + 1;
    int cy = n / 2 + 1;//(cx,cy)即中心坐标
    int k = max(abs(x-cx),abs(y-cy));//k表示在第几圈
    if(k == 0)return 1ll * n * n;
    //printf("\n(%d,%d) k : %d\n",x,y,k);
    ll res = d[k-1];//圈内有多少个
    //分4个case计算
    if(y-cy == k && x < cx + k){//在上层
        res += cx + k - x;
    }else if(cx - x == k && y < cy + k){//在左侧
        res += k * 2 + cy + k - y;
    }else if(cy - y == k && x > cx - k){//在下层
        res += k * 4 + x - (cx - k);
    }else if(x - cx == k){//在右侧
        res += k * 6 + y - (cy - k);
    }
    res = 1ll * n * n - res;//最后倒过来,因为上面是按照中心为1算的
    return res + 1;
}
int calc(ll x){
    int res= 0;
    while(x){res += x % 10;x /= 10;}
    return res;
}
int main(){
    scanf("%d",&T);
    d[0] = 1;d[1] = 8;
    for(int i=2;i<N;i++)d[i] = d[i-1] + 8;
    for(int i=1;i<N;i++)d[i] += d[i-1];//计算i圈以内有多少个点
    while(T--){
        mp.clear();v.clear();qu.clear();
        memset(c,0,sizeof c);
        scanf("%d%d%d",&n,&m,&p);
        for(int i=1;i<=m;i++){
            int x,y;
            scanf("%d%d",&x,&y);
            a[i] = {x,y,0};
        }
        for(int i=1;i<=p;i++){
            int x1,x2,y1,y2;
            scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
            qu.push_back({x1,y1,x2,y2});
            a[++m] = {x1-1,y1-1,1};
            a[++m] = {x2,y2,1};
            a[++m] = {x1-1,y2,1};
            a[++m] = {x2,y1-1,1};
        }
        for(int i=1;i<=m;i++){
            v.push_back(a[i].y);
        }
        sort(v.begin(),v.end());
        v.erase(unique(v.begin(),v.end()),v.end());
        sort(a+1,a+m+1,cmp);
        for(int i=1;i<=m;i++){
            id[i] = lower_bound(v.begin(),v.end(),a[i].y) - v.begin() + 1;
        }
        for(int i=1;i<=m;i++){
            if(a[i].type == 0)add(id[i],calc(get(a[i].x,a[i].y)));
            else if(a[i].type == 1)mp[a[i].x][a[i].y] = ask(id[i]);
        }
        for(int i=0;i<p;i++){
            int x1 = qu[i].x1,x2 = qu[i].x2,y1 = qu[i].y1,y2 = qu[i].y2;
            ll res = mp[x2][y2] + mp[x1-1][y1-1] - mp[x1-1][y2] - mp[x2][y1-1];
            printf("%lld\n",res);
        }
    }
    return 0;
}

D Robots

Set \ (D [u] \) is the desired number of days to u n, then there are:

\(d[u] = d[u] * {1\over outdeg[u]} + {1\over outdeg[u]} * \sum d[v] + 1\)

Set \ (F [u] \) of u n to the desired consumption, it has:

\(f[u] = {1\over outdeg[u]} *(f[u] + d[u]) + {1\over outdeg[u]} * \sum (f[v]+d[v]) + 1\)

Because you this day, every day after will have contributed an additional 1 u this point in the past, so to add d [u] and \ (\ sum d [v] \)

#include <bits/stdc++.h>
using namespace std;
const int N = 1e6+10;
int head[N],ver[N],nxt[N],tot,deg[N],sz[N];
int T,n,m;
void add(int x,int y){
    ver[++tot] = y;nxt[tot] = head[x];head[x] = tot;
}
double f[N],d[N];
int main(){
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&n,&m);
        tot = 0;
        for(int i=1;i<=n;i++){
            head[i] = 0;f[i] = d[i] = 0;deg[i] = 0;sz[i] = 0;
        }
        for(int i=1;i<=m;i++){
            int x,y;scanf("%d%d",&x,&y);
            add(y,x);
            deg[x]++;sz[x]++;
        }
        queue<int> q;
        q.push(n);
        while(q.size()){
            int x = q.front();q.pop();
            for(int i=head[x];i;i=nxt[i]){
                int y = ver[i];
                f[y] += f[x];
                d[y] += d[x];
                if(-- deg[y] == 0){
                    //if刚进来时,f[y] 和 d[y] 为 累加和
                    f[y] = ((d[y]+sz[y]+1)/sz[y]+f[y]+d[y]+sz[y]+1)/sz[y];
                    d[y] = (d[y] + sz[y] + 1)/sz[y];
                    q.push(y);
                }
            }
        }
        printf("%.2f\n",f[1]);
    }
    return 0;
}

F Greedy Sequence

Weight maximum number of segment tree maintenance occurred, i.e., [l,r]represents the number of all the current, the value in the \ ([l, r] \ ) the maximum number of the number range

Slide interval maintenance segment tree for every query, [1,x-1]the maximum number that appears if there is no answer 0

Finally, remember to search

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int T;
const int N = 100010;
int a[N],n,k,b[N],d[N];
struct Seg{
    int l,r;
    int mx;
}t[4*N];
void build(int p,int l,int r){
    t[p].l = l;t[p].r = r;
    if(l == r){
        t[p].mx = 0;return;
    }
    int mid = l + r >> 1;
    build(p*2,l,mid);
    build(p*2+1,mid+1,r);
    t[p].mx = 0;
}
void upd(int p,int x,int add){
    if(t[p].l == t[p].r && t[p].l == x){
        t[p].mx = add == 1 ? x : 0;
        return;
    }
    int mid = t[p].l + t[p].r >> 1;
    if(mid >= x)upd(p*2,x,add);
    if(mid < x)upd(p*2+1,x,add);
    t[p].mx = max(t[p*2].mx,t[p*2+1].mx);
}
int query(int p,int l,int r){
    if(t[p].l >= l && t[p].r <= r){
        return t[p].mx;
    }
    int mid = t[p].l + t[p].r >> 1;
    int res = 0;
    if(mid >= l)res = max(res,query(p*2,l,r));
    if(mid < r)res = max(res,query(p*2+1,l,r));
    return res;
}
ll get(int x){
    if(b[x] == 0)return d[x] = 1;
    if(d[x])return d[x];
    d[x] = get(b[x]) + 1;
    return d[x];
}
int main(){
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&n,&k);
        for(int i=1;i<=n;i++)scanf("%d",&a[i]);
        for(int i=1;i<=n;i++)d[i] = 0;
        int l = 1,r=min(1+k,n);
        build(1,1,n);
        for(int i=l;i<=r;i++){
            upd(1,a[i],1);
        }
        for(int i=1;i<=n;i++){
            b[a[i]] = query(1,1,a[i]-1);
            if(i-l>=k){
                upd(1,a[l],0);
                l++;
            }
            if(r<n){
                upd(1,a[++r],1);
            }
        }
        ll res = 0;
        for(int i=1;i<=n;i++)res += get(a[i]);
        for(int i=1;i<=n;i++){
            if(i>1)printf(" ");
            printf("%d",get(i));
        }
        puts("");
    }
    return 0;
}

H. Holy Grail

Every time I go the shortest path to return the answer is positive then add the negative side right, otherwise add positive side (be careful not to use Dijkstra)

#include <bits/stdc++.h>
using namespace std;
const int N = 1010;
typedef long long ll;
const ll INF = 1e18;
int head[N],ver[N],Nxt[N],tot;
int v[N],n,m;
ll edge[N],d[N];
void add(int x,int y,ll z){
    ver[++tot] = y;edge[tot] = z;Nxt[tot] = head[x];head[x] = tot;
}
ll dij(int s,int t){
    queue<int> q;
    for(int i = 0; i <= n + 5; i++){
        d[i] = INF;v[i] = 0;
    }
    d[s] = 0; q.push(s); v[s] = 1;
    while(q.size())
    {
        int x = q.front(); q.pop();
        v[x] = 0;
        for(int i = head[x]; i; i = Nxt[i]){
            int y = ver[i];
            if(d[y] > d[x] + edge[i])
            {
                d[y] = d[x] + edge[i];
                if(v[y] == 0){
                    v[y] = 1;
                    q.push(y);
                }
            }
        }
    }
    return d[t];
}
int main(){
    int T;scanf("%d",&T);
    for(int o=0;o<T;o++){
        scanf("%d%d",&n,&m);
        tot = 0;
        for(int i=1;i<=n;i++)head[i] = 0;
        for(int i=1;i<=m;i++){
            int x,y;
            ll z; 
            scanf("%d%d%lld",&x,&y,&z);
            x++;y++;
            add(x,y,z);
        }
        for(int j=1;j<=6;j++){
            int s,t;
            scanf("%d%d",&s,&t);
            s++;t++;
            ll dis = dij(t,s);
            printf("%lld\n",-dis);
            add(s,t,-dis);
        }
    }
    return 0;
}

Guess you like

Origin www.cnblogs.com/1625--H/p/11443960.html
Recommended