2019 ICPC 南京 网络赛
solve : 3/10
补题 : 5/10
https://www.jisuanke.com/contest/3004?view=challenges
A、The beautiful values of the palace
开场先开A,开了一眼这曲线不是去年蓝桥杯省赛的题吗,然后随便判了一下(大概15分钟)把值求出来了。
然后开始思考用线段树来实现nlogn,,因为 数据范围 看上去需要离散化,然后因为一开始只离散化了 个数字,然后upper_bound去找,然后又发现这样会找到 0 的情况(通过整体+1处理掉了)以及特别大的查询数字会被离散化为最后一个点的值,然后在离散化的地方Debug了巨久
写了一个半小时,Debug完了,队友怂恿我交一发,WA了,然后改成了 个值直接离散化,还是WA了,这个时候其实心态有点爆炸?我感觉A是个简单题,但实际上当时过的人并不多?以至于我觉得自己想了个假算法?
然后发现F题过的挺多的,随便推了一下,发现是个裸的主席树?(太假了,应该先直接开F
后期演了一波说这个线段树有问题,不能这样做。然后全队跑去开B。(其实是因为我使用的方法有问题。
感觉在决定要离散化的时候正常比赛就完了啊,离散化 也太恶心了啊,后面出现 1 1 3 3,这个询问被离散化为1 1 1 1,然后就改 ,然后整个人就死在处理离散化的路上了。
今天上午补了一波题,将线段树做法修正后,爆炸WA,然后看了一眼老哥代码,???
这个值等于数位和?不是,我不等于数位和为啥过了样例啊。原来最大的问题不是线段树,然后把第一发错误代码拉过来交了一下。居然过了,太假了
没有离散化的代码:
正确通过 | 2019-09-02 10:48 | 1148ms | 102728kB | c++ |
#include <bits/stdc++.h>
#define ll long long
#define sc scanf
#define pr printf
#define lson left,mid,k<<1
#define rson mid+1,right,k<<1|1
#define imid int mid=(left+right)/2;
using namespace std;
ll n, m, q;
ll gets(ll xx, ll yy)
{
ll x = -yy, y = -xx;
if (x >= 0)
{
if (y >= 0)
{
if (y >= x)
return 4 * y * y - y + x + 1;
else
return 4 * x * x + x - y + 1;
}
else
{
if (y >= -x)
return (2 * x + 1) * (2 * x) - x - y + 1;
else
return (1 - 2 * y) * (2 * (-y)) - x - y + 1;
}
}
else
{
if (y >= 0)
{
if (y >= -x)
return (2 * y) * (2 * y - 1) + x + y + 1;
else
return (2 * (-x)) * (2 * (-x) - 1) + x + y + 1;
}
else
{
if (y >= x + 1)
return (-1 - 2 * x) * (-1 - 2 * x) - x - 1 + y + 1;
else
return (1 - 2 * y) * (1 - 2 * y) - x - 1 + y + 1;
}
}
}
ll get(ll x, ll y)
{
return n * n - gets(x - (n + 1) / 2, y - (n + 1) / 2) + 1;
}
ll gg(ll num)
{
ll res = 0;
while (num)
{
res += num % 10;
num /= 10;
}
return res;
}
const int MAXN = 1e6 + 5;
struct node
{
int l;
int r;
ll sum;
}que[1000010 * 4];
int ql, qr;
ll val;
void up(int k)
{
que[k].sum = que[k << 1].sum + que[k << 1 | 1].sum;
}
void build(int left = 1, int right = MAXN, int k = 1)
{
que[k].l = left;
que[k].r = right;
que[k].sum = 0;
if (left == right)
return;
imid;
build(lson);
build(rson);
}
void update(int left = 1, int right = MAXN, int k = 1)
{
if (qr < left || right < ql)
return;
if (ql <= left && right <= qr)
{
que[k].sum = que[k].sum + val;
return;
}
imid;
update(lson);
update(rson);
up(k);
}
ll query(int left = 1, int right = MAXN, int k = 1)
{
if (qr < left || right < ql)
return 0;
if (ql <= left && right <= qr)
return que[k].sum;
imid;
return query(lson) + query(rson);
}
struct note
{
ll x;
ll y;
ll num;
}a[500005];
struct qq
{
ll x1;
ll y1;
ll x2;
ll y2;
}in[100005];
int cnt;
#define Pair pair<int,int>
int main()
{
int T;
sc("%d", &T);
while (T--)
{
map<Pair, ll>mp;
sc("%d%d%d", &n, &m, &q);
cnt = 0;
for (int i = 0; i < m; i++)
{
sc("%lld%lld", &a[i].x, &a[i].y);
a[i].num = get(a[i].x, a[i].y);
a[i].num = gg(a[i].num);
}
cnt = m;
for (int i = 0; i < q; i++)
{
sc("%lld%lld%lld%lld", &in[i].x1, &in[i].y1, &in[i].x2, &in[i].y2);
a[cnt++] = note{ in[i].x1 - 1, in[i].y1 - 1, 0 };
a[cnt++] = note{ in[i].x2, in[i].y2, 0 };
a[cnt++] = note{ in[i].x1 - 1, in[i].y2, 0 };
a[cnt++] = note{ in[i].x2, in[i].y1 - 1, 0 };
}
sort(a, a + cnt, [](note q, note w) {
if (q.x == w.x)
{
if (q.y == w.y)
return q.num > w.num;
else
return q.y < w.y;
}
return q.x < w.x;
});
build();
for (int i = 0; i < cnt; i++)
{
if (a[i].num == 0)
{
ql = 1, qr = a[i].y;
ll ans = query();
mp[Pair{ a[i].x,a[i].y }] = ans;
}
else
{
ql = qr = a[i].y, val = a[i].num;
update();
}
}
for (int i = 0; i < q; i++)
{
ll ans = mp[Pair{ in[i].x2,in[i].y2 }] - mp[Pair{ in[i].x1 - 1,in[i].y2 }] - mp[Pair{ in[i].x2,in[i].y1 - 1 }] + mp[Pair{ in[i].x1 - 1,in[i].y1 - 1 }];
pr("%lld\n", ans);
}
}
}
离散化的代码:
正确通过 | 2019-09-02 10:44 | 1440ms | 81632kB | c++ |
#include <bits/stdc++.h>
#define ll long long
#define sc scanf
#define pr printf
#define lson left,mid,k<<1
#define rson mid+1,right,k<<1|1
#define imid int mid=(left+right)/2;
using namespace std;
ll n, m, q;
ll gets(ll xx, ll yy)
{
ll x = -yy, y = -xx;
if (x >= 0)
{
if (y >= 0)
{
if (y >= x)
return 4 * y * y - y + x + 1;
else
return 4 * x * x + x - y + 1;
}
else
{
if (y >= -x)
return (2 * x + 1) * (2 * x) - x - y + 1;
else
return (1 - 2 * y) * (2 * (-y)) - x - y + 1;
}
}
else
{
if (y >= 0)
{
if (y >= -x)
return (2 * y) * (2 * y - 1) + x + y + 1;
else
return (2 * (-x)) * (2 * (-x) - 1) + x + y + 1;
}
else
{
if (y >= x + 1)
return (-1 - 2 * x) * (-1 - 2 * x) - x - 1 + y + 1;
else
return (1 - 2 * y) * (1 - 2 * y) - x - 1 + y + 1;
}
}
}
ll gg(ll num)
{
ll res = 0;
while (num)
{
res += num % 10;
num /= 10;
}
return res;
}
ll get(ll x, ll y)
{
return n * n - gets(x - (n + 1) / 2, y - (n + 1) / 2) + 1;
}
struct node
{
int l;
int r;
ll sum;
}que[500010 * 4];
int ql, qr;
ll val;
void up(int k)
{
que[k].sum = que[k << 1].sum + que[k << 1 | 1].sum;
}
void build(int left = 1, int right = 500005, int k = 1)
{
que[k].l = left;
que[k].r = right;
que[k].sum = 0;
if (left == right)
return;
imid;
build(lson);
build(rson);
}
void update(int left = 1, int right = 500005, int k = 1)
{
if (qr < left || right < ql)
return;
if (ql <= left && right <= qr)
{
que[k].sum = que[k].sum + val;
return;
}
imid;
update(lson);
update(rson);
up(k);
}
ll query(int left = 1, int right = 500005, int k = 1)
{
if (qr < left || right < ql)
return 0;
if (ql <= left && right <= qr)
return que[k].sum;
imid;
return query(lson) + query(rson);
}
struct in
{
ll x;
ll y;
ll num;
}a[500005];
struct qq
{
ll x1;
ll y1;
ll x2;
ll y2;
}qqq[100005];
ll qwe[100005][8];
int tx[500005], ty[500005];
int qqa, qqb, cnta, cntb, cnt;
void add(ll x, ll y)
{
a[cnt++] = in{ x,y,0 };
}
#define Pair pair<int,int>
int main()
{
int T;
sc("%d", &T);
while (T--)
{
map<Pair, ll>mp;
sc("%d%d%d", &n, &m, &q);
cnta = 0, cntb = 0;
cnt = 0;
for (int i = 0; i < m; i++)
{
sc("%lld%lld", &a[i].x, &a[i].y);
a[i].num = gg(get(a[i].x, a[i].y));
tx[cnta++] = a[i].x;
ty[cntb++] = a[i].y;
}
cnt = m;
for (int i = 0; i < q; i++)
{
sc("%lld%lld%lld%lld", &qqq[i].x1, &qqq[i].y1, &qqq[i].x2, &qqq[i].y2);
tx[cnta++] = qqq[i].x1 - 1;
tx[cnta++] = qqq[i].x2;
ty[cntb++] = qqq[i].y1 - 1;
ty[cntb++] = qqq[i].y2;
/*add(qqq[i].x1 - 1, qqq[i].y1 - 1);
add(qqq[i].x2, qqq[i].y2);
add(qqq[i].x1 - 1, qqq[i].y2);
add(qqq[i].x2, qqq[i].y1 - 1);
qqq[i].x1 = upper_bound(tx, tx + qqa, qqq[i].x1) - tx + 1;
qqq[i].x2 = upper_bound(tx, tx + qqa, qqq[i].x2) - tx + 1;
qqq[i].y1 = upper_bound(ty, ty + qqb, qqq[i].y1) - ty + 1;
qqq[i].y2 = upper_bound(ty, ty + qqb, qqq[i].y2) - ty + 1;*/
}
//a[cnt++] = in{ x,y,0 };
sort(tx, tx + cnta);
sort(ty, ty + cntb);
qqa = unique(tx, tx + cnta) - tx;
qqb = unique(ty, ty + cntb) - ty;
for (int i = 0; i < m; i++)
{
a[i].x = lower_bound(tx, tx + qqa, a[i].x) - tx + 1;
a[i].y = lower_bound(ty, ty + qqb, a[i].y) - ty + 1;
}
for (int i = 0; i < q; i++)
{
int q1 = lower_bound(tx, tx + qqa, qqq[i].x1 - 1) - tx + 1;
int w1 = lower_bound(ty, ty + qqb, qqq[i].y1 - 1) - ty + 1;
qwe[i][0] = q1;
qwe[i][1] = w1;
a[cnt++] = in{ q1,w1,0 };
q1 = lower_bound(tx, tx + qqa, qqq[i].x2) - tx + 1;
w1 = lower_bound(ty, ty + qqb, qqq[i].y1 - 1) - ty + 1;
qwe[i][2] = q1;
qwe[i][3] = w1;
a[cnt++] = in{ q1,w1,0 };
q1 = lower_bound(tx, tx + qqa, qqq[i].x1 - 1) - tx + 1;
w1 = lower_bound(ty, ty + qqb, qqq[i].y2) - ty + 1;
qwe[i][4] = q1;
qwe[i][5] = w1;
a[cnt++] = in{ q1,w1,0 };
q1 = lower_bound(tx, tx + qqa, qqq[i].x2) - tx + 1;
w1 = lower_bound(ty, ty + qqb, qqq[i].y2) - ty + 1;
qwe[i][6] = q1;
qwe[i][7] = w1;
a[cnt++] = in{ q1,w1,0 };
}
sort(a, a + cnt, [](in q, in w) {
if (q.x == w.x)
{
if (q.y == w.y)
return q.num > w.num;
else
return q.y < w.y;
}
return q.x < w.x;
});
build();
for (int i = 0; i < cnt; i++)
{
if (a[i].num == 0)
{
ql = 1, qr = a[i].y;
ll ans = query();
mp[Pair{ a[i].x,a[i].y }] = ans;
}
else
{
ql = qr = a[i].y, val = a[i].num;
update();
}
}
for (int i = 0; i < q; i++)
{
ll ans = mp[Pair{ qwe[i][6],qwe[i][7] }] - mp[Pair{ qwe[i][2],qwe[i][3] }] - mp[Pair{ qwe[i][4],qwe[i][5] }] + mp[Pair{ qwe[i][0],qwe[i][1] }];
pr("%lld\n", ans);
}
}
}
B、super_log
求 (b个a)。
欧拉降幂
欧拉定理:
降幂公式:
其中,第一个公式要求 a 和 mod 互质,第二第三个公式不要求 a mod 互质。
所以只要先搞最高次幂,递归就可以了,赛时快速幂没写欧拉降幂。
#include <bits/stdc++.h>
#define ll long long
#define sc scanf
#define pr printf
using namespace std;
ll power(ll a, ll b, ll mod)
{
ll res = 1;
while (b)
{
if (b & 1)
{
res = res * a;
if (res >= mod)
res = res % mod + mod;
}
a = a * a;
if (a >= mod)
a = a % mod + mod;
b >>= 1;
}
return res;
}
ll phi(ll n)
{
ll res = n;
for (ll i = 2; i * i <= n; i++)
{
if (n % i == 0)
{
res = res - res / i;
while (n % i == 0)
n /= i;
}
}
if (n > 1)
res = res - res / n;
return res;
}
ll dfs(ll n, ll m, ll cnt)
{
if (m == 1)
{
if (n == 0)
return 0;
else
return 1;
}
if (cnt == 1)
{
if (n >= m)
return n % m + m;
return n;
}
return power(n, dfs(n, phi(m), cnt - 1), m);
}
int main()
{
int T;
sc("%d", &T);
while (T--)
{
ll a, b, mod;
sc("%lld%lld%lld", &a, &b, &mod);
if (b == 0)
{
pr("%lld\n", 1 % mod);
continue;
}
else if (b == 1)
{
pr("%lld\n", a % mod);
continue;
}
else
{
b--;
ll ans = dfs(a, phi(mod), b);
ans = power(a, ans, mod);
pr("%lld\n", ans % mod);
}
}
}
F、Greedy Sequence
排个序,从小遍历到大,然后求一下这个数字在当前区间的个数k,然后求区间k-1小的值,然后转移
int id[MAXN];
int ans[MAXN];
int main()
{
int T;
sc("%d", &T);
while (T--)
{
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++)
{
scanf("%d", &a[i]);
t[i] = a[i];
id[a[i]] = i;
ans[i] = 0;
}
sort(t + 1, t + 1 + n);
int qq = unique(t + 1, t + 1 + n) - t - 1;
for (int i = 1; i <= n; i++)
a[i] = lower_bound(t + 1, t + qq + 1, a[i]) - t;
init();
for (int i = 1; i <= n; i++)
{
root[i] = root[i - 1];
build(a[i], root[i], 1, n);
}
int ql, qr, k;
for (int i = 1; i <= n; i++)
{
ql = max(id[i] - m, 1);
qr = min(id[i] + m, n);
int tot = querycnt(root[ql - 1], root[qr], 1, i, 1, n);
k = tot - 1;
if (k == 0)
{
ans[i] = 1;
}
else
{
int pos = query(root[ql - 1], root[qr], k, 1, n);
ans[i] = ans[pos] + 1;
}
}
for (int i = 1; i <= n; i++)
pr("%d%c", ans[i], i == n ? '\n' : ' ');
}
}
H、Holy Grail
#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 10005
#define M 20005
using namespace std;
typedef long long ll;
const ll INF = 1e12;
ll n,m,t;
ll v[M],w[M],nextt[M];
ll d[N],cnt[N],first[N];
bool vis[N];
void add(ll x,ll y,ll z)
{
t++;
nextt[t]=first[x];
first[x]=t;
v[t]=y;
w[t]=z;
}
bool SPFA(ll s)
{
ll x,y,i,j;
queue<ll>q;
for(int i=0;i<=n;++i) d[i]=INF,vis[i]=false;
// memset(d,127,sizeof(d));
// memset(vis,false,sizeof(vis));
while(!q.empty()) q.pop();
d[s]=0;
cnt[s]=1;
q.push(s);
vis[s]=true;
while(!q.empty())
{
x=q.front();
q.pop();
vis[x]=false;
for(i=first[x];i;i=nextt[i])
{
y=v[i];
if(d[y]>d[x]+w[i])
{
d[y]=d[x]+w[i];
cnt[y]=cnt[x]+1;
if(cnt[y]>n)
return false;
if(!vis[y])
{
q.push(y);
vis[y]=true;
}
}
}
}
return true;
}
int main()
{
ll T;
scanf("%lld",&T);
while(T--){
ll x,y,z,i;
scanf("%lld%lld",&n,&m);
for(int i=0;i<=n;++i) first[i]=0;
t=0;
for(i=1;i<=m;++i)
{
scanf("%lld%lld%lld",&x,&y,&z);
add(x,y,z);
}
for(int i=1;i<=6;++i){
ll a,b;
scanf("%lld%lld",&a,&b);
ll c = -INF;
add(a,b,c);
ll l = -2e12,r = 1e12;
ll ans;
while(l+1<r){
ll mid = (l+r)>>1;
w[t]=mid;
if(!SPFA(b)) l=mid;
else r=mid;
}
w[t]=l;
if(!SPFA(b))
ans=r;
else ans=l;
printf("%lld\n",ans);
w[t]=ans;
}
}
return 0;
}