http://main.edu.pl/en/archive/oi/21/kur
題目:區間查詢有沒有數字的量嚴格大於一半,假如有就輸出,沒有則輸出0
一直覺得很神奇XD 首先抓出候選人,然後真的去確認他的數量
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <vector>
#include <map>
using namespace std;
struct node{int id, hp; node(int _id = 0, int _hp = 0):id(_id),hp(_hp){return;}};
node operator+(const node& a, const node& b){
node ret;
if(a.id == b.id){
ret = node(a.id, a.hp+b.hp);
}else if(a.hp > b.hp){
ret = node(a.id, a.hp-b.hp);
}else{
ret = node(b.id, b.hp-a.hp);
}
if(ret.hp == 0) ret.id = 0;
return ret;
}
struct sumbst{
vector<node> tree;
int base;
sumbst(int n, int* arr){
base = (1<<(int)(ceil)(log2(n+3)))-1;
tree = vector<node>(base*2+2, node());
for(int lx = 0; lx < n;lx++)
tree[lx+base+2] = node(arr[lx], 1);
for(int lx = base;lx;lx--)
tree[lx] = tree[lx<<1]+tree[(lx<<1)^1];
}
int query(int a, int b){
node ret;
for(a += base+1, b += base+3;a^b^1;a>>=1, b>>=1){
if(~a&1) ret = ret + tree[a^1];
if(b&1) ret = ret + tree[b^1];
}
return ret.id;
}
};
int arr[500000];
map<int, vector<int> > qmap;
int main(){
int n, q; scanf("%d %d", &n, &q);
for(int lx = 0;lx < n;lx++) scanf("%d", arr+lx);
for(int lx = 0;lx < n;lx++) qmap[arr[lx]].push_back(lx);
sumbst bst(n, arr);
for(int lx = 0;lx < q;lx++){
int a, b; scanf("%d %d", &a, &b); a--, b--;
int id = bst.query(a, b);
if(id == 0){ printf("0\n"); continue;}
vector<int>& vec = qmap[id];
int lowptr = lower_bound(vec.begin(), vec.end(), a) - vec.begin();
int uppptr = upper_bound(vec.begin(), vec.end(), b) - vec.begin();
int count = uppptr-lowptr;
if(count > (b-a+1)/2)
printf("%d\n", id);
else
printf("0\n");
}
return 0;
}
2015年6月5日 星期五
TIOJ 1106 . 遇見一株樹
#include <cstdio>
#include <cstdlib>
#include <algorithm>
using namespace std;
struct node{
int nc, h;
node(int _h = 0){nc = 0;h = _h;return;}
}stk[1000000];
int ptr;
char buf[1000000];
int main(){
while(scanf("%s", buf) != EOF){
ptr = 1;
stk[0] = node(1);
int max_nc = 0;
int max_h = 1;
int leaf_cnt = 0;
for(int lx = 0;buf[lx] != 0;lx++){
if(buf[lx] == '('){
stk[ptr-1].nc++;
stk[ptr] = node(stk[ptr-1].h+1);
ptr++;
}else if(buf[lx] == ')'){
max_h = max(max_h, stk[ptr-1].h);
max_nc = max(max_nc, stk[ptr-1].nc);
ptr--;
}else if(buf[lx] == '*'){
stk[ptr-1].nc++;
leaf_cnt++;
}
}
printf("%d %d %d\n", leaf_cnt, max_h, max_nc);
}
return 0;
}
DQUERY - D-query
跟兔子王國類似的手法,對Query x排序,準備sumbst,處理pop數字ptr和push數字ptr..
[兔子王國]
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <map>
#include <cmath>
using namespace std;
struct sumbst{
vector<int> tree;
int base;
sumbst(int n){
base = (1<<(int)(ceil(log2(n+3))))-1;
tree = vector<int>(2*base+2, 0);
return;
}
void modify(int p, int v){
p += base + 2;
tree[p] = v;
for(p>>=1;p;p>>=1)
tree[p] = tree[p<<1] + tree[(p<<1)^1];
return;
}
int query(int a, int b){
int ret = 0;
for(a+=base+1,b+=base+3; a^b^1;a>>=1, b>>=1){
if(~a&1) ret += tree[a^1];
if(b&1) ret += tree[b^1];
}
return ret;
}
};
struct qry{int id, x, y;};
bool operator<(const qry& a, const qry& b){return a.x < b.x;}
int arr[200000];
int main(){
int n; scanf("%d", &n);
for(int lx = 0;lx < n;lx++)
scanf("%d", arr+lx);
map<int, vector<int> > posrec;
map<int, int > posptr;
for(int lx = 0;lx < n;lx++){
posrec[arr[lx]].push_back(lx);
posptr[arr[lx]] = 1;
}
int q; scanf("%d", &q);
vector<qry> qrys(q);
for(int lx = 0;lx < q;lx++){
int a, b;
scanf("%d %d", &a, &b);
qrys[lx].x = a-1, qrys[lx].y = b-1, qrys[lx].id = lx;
}
sort(qrys.begin(), qrys.end());
vector<int> ans(q);
sumbst bst(n);
for(auto& it : posrec)
bst.modify(it.second[0], 1);
int now = 0;
for(qry& qq : qrys){
while(now < qq.x){
auto& vec = posrec[arr[now]];
auto& ptr = posptr[arr[now]];
bst.modify(vec[ptr-1], 0);
if(vec.size() > ptr)
bst.modify(vec[ptr], 1);
ptr++, now++;
}
ans[qq.id] = bst.query(qq.x, qq.y);
}
for(int lx = 0;lx < q;lx++)
printf("%d\n", ans[lx]);
return 0;
}
[兔子王國]
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <map>
#include <cmath>
using namespace std;
struct sumbst{
vector<int> tree;
int base;
sumbst(int n){
base = (1<<(int)(ceil(log2(n+3))))-1;
tree = vector<int>(2*base+2, 0);
return;
}
void modify(int p, int v){
p += base + 2;
tree[p] = v;
for(p>>=1;p;p>>=1)
tree[p] = tree[p<<1] + tree[(p<<1)^1];
return;
}
int query(int a, int b){
int ret = 0;
for(a+=base+1,b+=base+3; a^b^1;a>>=1, b>>=1){
if(~a&1) ret += tree[a^1];
if(b&1) ret += tree[b^1];
}
return ret;
}
};
struct qry{int id, x, y;};
bool operator<(const qry& a, const qry& b){return a.x < b.x;}
int arr[200000];
int main(){
int n; scanf("%d", &n);
for(int lx = 0;lx < n;lx++)
scanf("%d", arr+lx);
map<int, vector<int> > posrec;
map<int, int > posptr;
for(int lx = 0;lx < n;lx++){
posrec[arr[lx]].push_back(lx);
posptr[arr[lx]] = 1;
}
int q; scanf("%d", &q);
vector<qry> qrys(q);
for(int lx = 0;lx < q;lx++){
int a, b;
scanf("%d %d", &a, &b);
qrys[lx].x = a-1, qrys[lx].y = b-1, qrys[lx].id = lx;
}
sort(qrys.begin(), qrys.end());
vector<int> ans(q);
sumbst bst(n);
for(auto& it : posrec)
bst.modify(it.second[0], 1);
int now = 0;
for(qry& qq : qrys){
while(now < qq.x){
auto& vec = posrec[arr[now]];
auto& ptr = posptr[arr[now]];
bst.modify(vec[ptr-1], 0);
if(vec.size() > ptr)
bst.modify(vec[ptr], 1);
ptr++, now++;
}
ans[qq.id] = bst.query(qq.x, qq.y);
}
for(int lx = 0;lx < q;lx++)
printf("%d\n", ans[lx]);
return 0;
}
2015年6月4日 星期四
HOJ 327 - 兔子王國
http://hoj.twbbs.org/judge/problem/view/327
題目:給一串數列,和一堆查詢,每次查詢[a, b]之間有多少數字和這區間其他數互質,不強迫在線,多筆測資
N = 200000, Time Limit = 3000/per file
是某區域賽,原本想了個36*N^1.5的做法,可是T了,大概是因為常數再加上多筆測資,只好怒看題解。
主要概念是對每個數字紀錄和他互質最左界可以到哪裡,最右界可以到哪裡。
對於一個區間,我們希望的答案就是 數字左界<=區間左界 且 數字右界>=區間右界 的個數
然後對查詢做離線處理,根據查詢區間左界做排序。
準備一個和線段樹。對於每筆查詢,我們都要先像是維護單調性調整左界,
(1) 當一個數字的左界被左指標指到時, 這個數字可能可以在接下來的查詢出現
(2) 當一個數字的位置被左指標超越時,這個數字不可能在接下來的查詢出現
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <cmath>
#include <algorithm>
using namespace std;
struct sumbst{ // 0-base
int base;
vector<int> tree;
sumbst(int n){
base = (1<<(int)(ceil(log2(n+3))))-1;
tree = vector<int>(2*base+2, 0);
return;
}
void modify(int p, int v){
p += base+2; tree[p] += v;
for(p>>=1;p;p>>=1) tree[p] = tree[p<<1] + tree[(p<<1)^1];
return;
}
int query(int a, int b){
int ret = 0;
for(a += base+1, b += base+3;a^b^1;a>>=1, b>>=1){
if(~a&1) ret += tree[a^1];
if(b&1) ret += tree[b^1];
}
return ret;
}
};
int arr[200000];
vector<int> rad[200001];
int rn[200000];
vector<int> adat[200000];
void make(int n){
for(int lx = 0;lx < n;lx++) adat[lx].clear();
vector<int> ap(200000, 0);
for(int lx = 0;lx < n;lx++){
int pos = 0;
for(int pp : rad[arr[lx]]){
pos = max(pos, ap[pp]);
ap[pp] = lx+1;
}
adat[pos].push_back(lx);
}
ap = vector<int>(200000, n-1);
for(int lx = n-1;lx >= 0;lx--){
int pos = n-1;
for(int pp : rad[arr[lx]]){
pos = min(pos, ap[pp]);
ap[pp] = lx-1;
}
rn[lx] = pos;
}
return;
}
struct qry{
int x,y,id;
qry(int _x = 0, int _y = 0, int _id = 0):x(_x), y(_y), id(_id){return;}
};
bool operator<(const qry& a, const qry& b){return a.x < b.x;}
int main(){
{
vector<int> seive(200000, 1);
for(int lx = 2;lx < 200000;lx++)
if(seive[lx])
for(int ly = 1;ly*lx <= 200000;ly++)
rad[ly*lx].push_back(lx), seive[lx*ly] = 0;
}
int n, q;
while(scanf("%d %d", &n, &q) != EOF){
for(int lx = 0;lx < n;lx++) scanf("%d", arr+lx);
make(n);
vector<qry> qrys(q);
for(int lx = 0;lx < q;lx++){
int x, y; scanf("%d %d", &x, &y);
x--, y--;
qrys[lx] = qry(x, y, lx);
}
sort(qrys.begin(), qrys.end());
vector<int> ans(q, 0);
sumbst bst(n+1);
int nl = -1;
for(qry& qq : qrys){
while(nl < qq.x){
if(nl != -1){
bst.modify(nl, -1);
bst.modify(rn[nl]+1, 1);
}
nl++;
for(int id: adat[nl]){
bst.modify(id, 1);
bst.modify(rn[id]+1, -1);
}
}
ans[qq.id] = bst.query(qq.x, qq.y);
}
for(int lx = 0;lx < q;lx++)
printf("%d\n", ans[lx]);
}
return 0;
}
題目:給一串數列,和一堆查詢,每次查詢[a, b]之間有多少數字和這區間其他數互質,不強迫在線,多筆測資
N = 200000, Time Limit = 3000/per file
是某區域賽,原本想了個36*N^1.5的做法,可是T了,大概是因為常數再加上多筆測資,只好怒看題解。
主要概念是對每個數字紀錄和他互質最左界可以到哪裡,最右界可以到哪裡。
對於一個區間,我們希望的答案就是 數字左界<=區間左界 且 數字右界>=區間右界 的個數
然後對查詢做離線處理,根據查詢區間左界做排序。
準備一個和線段樹。對於每筆查詢,我們都要先像是維護單調性調整左界,
(1) 當一個數字的左界被左指標指到時, 這個數字可能可以在接下來的查詢出現
(2) 當一個數字的位置被左指標超越時,這個數字不可能在接下來的查詢出現
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <cmath>
#include <algorithm>
using namespace std;
struct sumbst{ // 0-base
int base;
vector<int> tree;
sumbst(int n){
base = (1<<(int)(ceil(log2(n+3))))-1;
tree = vector<int>(2*base+2, 0);
return;
}
void modify(int p, int v){
p += base+2; tree[p] += v;
for(p>>=1;p;p>>=1) tree[p] = tree[p<<1] + tree[(p<<1)^1];
return;
}
int query(int a, int b){
int ret = 0;
for(a += base+1, b += base+3;a^b^1;a>>=1, b>>=1){
if(~a&1) ret += tree[a^1];
if(b&1) ret += tree[b^1];
}
return ret;
}
};
int arr[200000];
vector<int> rad[200001];
int rn[200000];
vector<int> adat[200000];
void make(int n){
for(int lx = 0;lx < n;lx++) adat[lx].clear();
vector<int> ap(200000, 0);
for(int lx = 0;lx < n;lx++){
int pos = 0;
for(int pp : rad[arr[lx]]){
pos = max(pos, ap[pp]);
ap[pp] = lx+1;
}
adat[pos].push_back(lx);
}
ap = vector<int>(200000, n-1);
for(int lx = n-1;lx >= 0;lx--){
int pos = n-1;
for(int pp : rad[arr[lx]]){
pos = min(pos, ap[pp]);
ap[pp] = lx-1;
}
rn[lx] = pos;
}
return;
}
struct qry{
int x,y,id;
qry(int _x = 0, int _y = 0, int _id = 0):x(_x), y(_y), id(_id){return;}
};
bool operator<(const qry& a, const qry& b){return a.x < b.x;}
int main(){
{
vector<int> seive(200000, 1);
for(int lx = 2;lx < 200000;lx++)
if(seive[lx])
for(int ly = 1;ly*lx <= 200000;ly++)
rad[ly*lx].push_back(lx), seive[lx*ly] = 0;
}
int n, q;
while(scanf("%d %d", &n, &q) != EOF){
for(int lx = 0;lx < n;lx++) scanf("%d", arr+lx);
make(n);
vector<qry> qrys(q);
for(int lx = 0;lx < q;lx++){
int x, y; scanf("%d %d", &x, &y);
x--, y--;
qrys[lx] = qry(x, y, lx);
}
sort(qrys.begin(), qrys.end());
vector<int> ans(q, 0);
sumbst bst(n+1);
int nl = -1;
for(qry& qq : qrys){
while(nl < qq.x){
if(nl != -1){
bst.modify(nl, -1);
bst.modify(rn[nl]+1, 1);
}
nl++;
for(int id: adat[nl]){
bst.modify(id, 1);
bst.modify(rn[id]+1, -1);
}
}
ans[qq.id] = bst.query(qq.x, qq.y);
}
for(int lx = 0;lx < q;lx++)
printf("%d\n", ans[lx]);
}
return 0;
}
2015年6月3日 星期三
TIOJ 1085 . 三維迷宮問題
#include <cstdio>
#include <cstdlib>
#include <queue>
#include <vector>
#include <cstring>
using namespace std;
int gx(int a){return (a%50) + 1;}
int gy(int a){return ((a/50)%50) + 1;}
int gz(int a){return ((a/2500)%50) + 1;}
int tv(int x, int y, int z){return (x-1) + (y-1)*50 + (z-1)*2500;}
int tab[52][52][52] = {0};
int vis[52][52][52];
int main(){
int xx, yy, zz; scanf("%d %d %d", &xx, &yy, &zz);
memset(vis, -1, sizeof(vis));
for(int lx = 1;lx <= xx;lx++) for(int ly = 1;ly <= yy;ly++) tab[lx][ly][0] = tab[lx][ly][zz+1] = 1;
for(int lx = 1;lx <= xx;lx++) for(int lz = 1;lz <= zz;lz++) tab[lx][0][lz] = tab[lx][yy+1][lz] = 1;
for(int lz = 1;lz <= zz;lz++) for(int ly = 1;ly <= yy;ly++) tab[0][ly][lz] = tab[xx+1][ly][lz] = 1;
for(int lz = 1;lz <= zz;lz++)
for(int ly = 1;ly <= yy;ly++)
for(int lx = 1;lx <= xx;lx++)
scanf("%d", &tab[lx][ly][lz]);
if(tab[1][1][1]){
puts("no route");
return 0;
}
vis[1][1][1] = 0;
queue<int> que;
que.push(0);
const int dx[] = {0, 0, 0, 0, 1, -1},
dy[] = {1, -1, 0, 0, 0, 0},
dz[] = {0, 0, 1, -1, 0, 0};
while(que.size()){
int prc = que.front(); que.pop();
int px = gx(prc), py = gy(prc), pz = gz(prc);
for(int t = 0;t < 6;t++){
int nx = px + dx[t], ny = py + dy[t], nz = pz + dz[t];
if(tab[nx][ny][nz]) continue;
if(vis[nx][ny][nz]!=-1) continue;
vis[nx][ny][nz] = prc;
que.push(tv(nx, ny, nz));
}
}
if(vis[xx][yy][zz] == -1){
puts("no route");
return 0;
}
vector<int> hist;
int now = tv(xx, yy, zz);
while(now){
hist.push_back(now);
now = vis[gx(now)][gy(now)][gz(now)];
}
printf("(1,1,1)");
for(int lx = ((int)hist.size())-1;lx>=0;lx--){
int prc = hist[lx];
printf("->(%d,%d,%d)",gx(prc),gy(prc),gz(prc));
}
puts("");
return 0;
}
TIOJ 1084 . 一筆畫問題
dfs倒著吐回去
#include <cstdio>
#include <cstdlib>
#include <cstring>
using namespace std;
int tab[500][500];
int vcnt[500];
int stk[1025], stkcnt;
void dfs(int a){
bool flag = false;
for(int lx = 0;lx < 500;lx++){
if(tab[a][lx]){
tab[a][lx]--;
tab[lx][a]--;
dfs(lx);
flag = true;
stk[stkcnt++] = a+1;
}
}
if(!flag) stk[stkcnt++] = a+1;
return;
}
int main(){
int c;
while(scanf("%d", &c)&&c){
memset(tab, 0, sizeof(tab));
memset(vcnt, 0, sizeof(vcnt));
stkcnt = 0;
while(c--){
int a, b; scanf("%d %d", &a, &b); a--, b--;
tab[a][b]++, tab[b][a]++;
vcnt[a]++, vcnt[b]++;
}
bool check = true;
for(int lx = 0;lx < 500 and check;lx++)
check = not (vcnt[lx]&1);
int sm = -1;
if(check) while(!vcnt[++sm]);
else while(!(vcnt[++sm]&1));
dfs(sm);
for(int lx = stkcnt-1;lx>=0;lx--)
if(lx == stkcnt-1 or stk[lx] != stk[lx+1])
printf("%d\n", stk[lx]);
puts("");
}
return 0;
}
#include <cstdio>
#include <cstdlib>
#include <cstring>
using namespace std;
int tab[500][500];
int vcnt[500];
int stk[1025], stkcnt;
void dfs(int a){
bool flag = false;
for(int lx = 0;lx < 500;lx++){
if(tab[a][lx]){
tab[a][lx]--;
tab[lx][a]--;
dfs(lx);
flag = true;
stk[stkcnt++] = a+1;
}
}
if(!flag) stk[stkcnt++] = a+1;
return;
}
int main(){
int c;
while(scanf("%d", &c)&&c){
memset(tab, 0, sizeof(tab));
memset(vcnt, 0, sizeof(vcnt));
stkcnt = 0;
while(c--){
int a, b; scanf("%d %d", &a, &b); a--, b--;
tab[a][b]++, tab[b][a]++;
vcnt[a]++, vcnt[b]++;
}
bool check = true;
for(int lx = 0;lx < 500 and check;lx++)
check = not (vcnt[lx]&1);
int sm = -1;
if(check) while(!vcnt[++sm]);
else while(!(vcnt[++sm]&1));
dfs(sm);
for(int lx = stkcnt-1;lx>=0;lx--)
if(lx == stkcnt-1 or stk[lx] != stk[lx+1])
printf("%d\n", stk[lx]);
puts("");
}
return 0;
}
2015年5月31日 星期日
Codeforces Round #305 (Div. 1), problem: (C) Mike and Foam
排容w
#include <cstdio> #include <cstdlib> #include <vector> #include <algorithm> using namespace std; typedef long long int int64; vector<int> primes; vector<int> radi[5000001]; bool has[200000] = {0}; int has_count = 0; int arr[200000]; int64 tab[500001] = {0}; void dump(int n){ printf("radical %d : ", n); for(int ii : radi[n]) printf("%d ", ii); puts(""); return; } int main(){ {vector<bool> seive(500000, 0); for(int lx = 2;lx < 500000;lx++) if(seive[lx] == 0) for(int ly = 2;ly*lx < 500000;ly++) seive[ly*lx] = 1; for(int lx = 2;lx < 500000;lx++) if(seive[lx] == 0) primes.push_back(lx); } for(int lx = 0;lx < primes.size();lx++){ int p = primes[lx]; for(int ly = 1;ly*p <= 500000; ly++) radi[ly*p].push_back(p); } int n, q; scanf("%d %d", &n, &q); for(int lx = 0;lx < n;lx++) scanf("%d", arr+lx); int64 count = 0; while(q--){ int _inp; scanf("%d", &_inp); _inp--; int inp = arr[_inp]; //printf("q %d\n", inp); int pc = radi[inp].size(); if(has[_inp] == 0){ int64 aa = 0; for(int sts = 0;sts < (1<<pc);sts++){ int val = 1; int64 sign = 1; for(int lx = 0;lx < pc;lx++) if(sts&(1<<lx)) sign *= -1, val *= radi[inp][lx]; aa += tab[val]*sign; tab[val]++; } count += aa; }else{ int64 aa = 0; for(int sts = 0;sts < (1<<pc);sts++){ int val = 1; int64 sign = 1; for(int lx = 0;lx < pc;lx++) if(sts&(1<<lx)) sign *= -1, val *= radi[inp][lx]; aa += (tab[val]-1)*sign; tab[val]--; } count -= aa; } has[_inp] ^= 1; printf("%I64d\n", count); } return 0; }
訂閱:
文章 (Atom)